living_document 1.1.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +0 -4
- data/Gemfile.lock +18 -24
- data/README.md +36 -2
- data/exe/livdoc +58 -19
- data/lib/living_document/code_evaluator.rb +32 -20
- data/lib/living_document/platform_check.rb +9 -0
- data/lib/living_document/version.rb +1 -1
- data/lib/living_document.rb +2 -0
- data/living_document.gemspec +4 -1
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3680ab9cf85cc909a679c876a1dcdc5ce3f5e870419efa17770208f4c7359bb5
|
4
|
+
data.tar.gz: 76edf601a178c8afc1d88040f591a4b8e4026282bdf5d4dec3c4b415f36af01e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5173bd8e3e6d4c96017db480009272e8016af8b2735281ccafbef5a673ed079dd0163a43bea963222e603a8be84e5cf0081c641dc92fbb68fd0bf0da295e9bc5
|
7
|
+
data.tar.gz: 2ebc0946d141e3b18b5d84cc792ce88d88f1f749745294efa566f6074a23063665596064e8a672e9c5cf504343261bf8d0af8ee0dd0003da0e7634c87ea9e8b4
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## v2.1.0 (2025-02-05)
|
2
|
+
- Offer to create the provided target file, if it doesn't yet exist.
|
3
|
+
- Document compatibility with VS Code and NeoVim.
|
4
|
+
- Automatically open the target file in editor, if `$EDITOR` is set.
|
5
|
+
|
6
|
+
## v2.0.0 (2025-02-05)
|
7
|
+
- **BREAKING:** Use `rb-inotify` (not `listen`) to watch for file changes. This means that the gem is now only compatible with Linux.
|
8
|
+
- Support listening to files outside of the current directory.
|
9
|
+
|
1
10
|
## v1.1.1 (2025-01-30)
|
2
11
|
- Fix exception when evaluating an empty target file. https://github.com/davidrunger/living_document/pull/608
|
3
12
|
|
data/Gemfile
CHANGED
@@ -9,14 +9,10 @@ gemspec
|
|
9
9
|
|
10
10
|
group :development, :test do
|
11
11
|
gem 'amazing_print'
|
12
|
-
# Remove if/when byebug brings in this dependency for us.
|
13
|
-
gem 'irb'
|
14
12
|
gem 'pry'
|
15
13
|
# Go back to upstream if/when https://github.com/deivid-rodriguez/pry-byebug/pull/ 428 is merged.
|
16
14
|
gem 'pry-byebug', github: 'davidrunger/pry-byebug'
|
17
15
|
gem 'rake'
|
18
|
-
# Remove if/when byebug brings in this dependency for us.
|
19
|
-
gem 'reline'
|
20
16
|
gem 'rubocop', require: false
|
21
17
|
gem 'rubocop-performance', require: false
|
22
18
|
gem 'rubocop-rake', require: false
|
data/Gemfile.lock
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/davidrunger/pry-byebug.git
|
3
|
-
revision:
|
3
|
+
revision: 3ac27ef70a1b16a461db9f7572d3fe1a205effd4
|
4
4
|
specs:
|
5
5
|
pry-byebug (3.10.1)
|
6
|
-
byebug (>= 11.0)
|
7
6
|
pry (>= 0.13)
|
7
|
+
runger_byebug (>= 11.0)
|
8
8
|
|
9
9
|
PATH
|
10
10
|
remote: .
|
11
11
|
specs:
|
12
|
-
living_document (
|
12
|
+
living_document (2.1.0)
|
13
13
|
activesupport (>= 6)
|
14
|
-
listen (>= 3.2)
|
15
14
|
memo_wise (>= 1.7)
|
15
|
+
rb-inotify (>= 0.11.1)
|
16
16
|
timecop (>= 0.9.10)
|
17
17
|
|
18
18
|
GEM
|
@@ -36,7 +36,6 @@ GEM
|
|
36
36
|
base64 (0.2.0)
|
37
37
|
benchmark (0.4.0)
|
38
38
|
bigdecimal (3.1.9)
|
39
|
-
byebug (11.1.3)
|
40
39
|
coderay (1.1.3)
|
41
40
|
concurrent-ruby (1.3.5)
|
42
41
|
connection_pool (2.5.0)
|
@@ -64,15 +63,12 @@ GEM
|
|
64
63
|
reline (>= 0.4.2)
|
65
64
|
json (2.9.1)
|
66
65
|
language_server-protocol (3.17.0.4)
|
67
|
-
listen (3.9.0)
|
68
|
-
rb-fsevent (~> 0.10, >= 0.10.3)
|
69
|
-
rb-inotify (~> 0.9, >= 0.9.10)
|
70
66
|
logger (1.6.5)
|
71
67
|
memo_wise (1.10.0)
|
72
68
|
method_source (1.1.0)
|
73
69
|
minitest (5.25.4)
|
74
70
|
parallel (1.26.3)
|
75
|
-
parser (3.3.7.
|
71
|
+
parser (3.3.7.1)
|
76
72
|
ast (~> 2.4.1)
|
77
73
|
racc
|
78
74
|
pp (0.6.2)
|
@@ -88,7 +84,6 @@ GEM
|
|
88
84
|
racc (1.8.1)
|
89
85
|
rainbow (3.1.1)
|
90
86
|
rake (13.2.1)
|
91
|
-
rb-fsevent (0.11.2)
|
92
87
|
rb-inotify (0.11.1)
|
93
88
|
ffi (~> 1.0)
|
94
89
|
rdoc (6.11.0)
|
@@ -110,14 +105,14 @@ GEM
|
|
110
105
|
diff-lcs (>= 1.2.0, < 2.0)
|
111
106
|
rspec-support (~> 3.13.0)
|
112
107
|
rspec-support (3.13.2)
|
113
|
-
rubocop (1.71.
|
108
|
+
rubocop (1.71.2)
|
114
109
|
json (~> 2.3)
|
115
110
|
language_server-protocol (>= 3.17.0)
|
116
111
|
parallel (~> 1.10)
|
117
112
|
parser (>= 3.3.0.2)
|
118
113
|
rainbow (>= 2.2.2, < 4.0)
|
119
114
|
regexp_parser (>= 2.9.3, < 3.0)
|
120
|
-
rubocop-ast (>= 1.
|
115
|
+
rubocop-ast (>= 1.38.0, < 2.0)
|
121
116
|
ruby-progressbar (~> 1.7)
|
122
117
|
unicode-display_width (>= 2.4.0, < 4.0)
|
123
118
|
rubocop-ast (1.38.0)
|
@@ -128,12 +123,15 @@ GEM
|
|
128
123
|
rubocop-rake (0.6.0)
|
129
124
|
rubocop (~> 1.0)
|
130
125
|
ruby-progressbar (1.13.0)
|
131
|
-
|
126
|
+
runger_byebug (11.3.0)
|
127
|
+
irb
|
128
|
+
reline
|
129
|
+
runger_release_assistant (2.0.0)
|
132
130
|
activesupport (>= 6)
|
133
131
|
memo_wise (>= 1.7)
|
134
132
|
rainbow (>= 3.0)
|
135
133
|
slop (~> 4.8)
|
136
|
-
runger_style (4.
|
134
|
+
runger_style (4.3.0)
|
137
135
|
prism (>= 0.24.0)
|
138
136
|
rubocop (>= 1.68.0)
|
139
137
|
securerandom (0.4.1)
|
@@ -171,12 +169,10 @@ PLATFORMS
|
|
171
169
|
|
172
170
|
DEPENDENCIES
|
173
171
|
amazing_print
|
174
|
-
irb
|
175
172
|
living_document!
|
176
173
|
pry
|
177
174
|
pry-byebug!
|
178
175
|
rake
|
179
|
-
reline
|
180
176
|
rspec
|
181
177
|
rubocop
|
182
178
|
rubocop-performance
|
@@ -192,7 +188,6 @@ CHECKSUMS
|
|
192
188
|
base64 (0.2.0) sha256=0f25e9b21a02a0cc0cea8ef92b2041035d39350946e8789c562b2d1a3da01507
|
193
189
|
benchmark (0.4.0) sha256=0f12f8c495545e3710c3e4f0480f63f06b4c842cc94cec7f33a956f5180e874a
|
194
190
|
bigdecimal (3.1.9) sha256=2ffc742031521ad69c2dfc815a98e426a230a3d22aeac1995826a75dabfad8cc
|
195
|
-
byebug (11.1.3) sha256=2485944d2bb21283c593d562f9ae1019bf80002143cc3a255aaffd4e9cf4a35b
|
196
191
|
coderay (1.1.3) sha256=dc530018a4684512f8f38143cd2a096c9f02a1fc2459edcfe534787a7fc77d4b
|
197
192
|
concurrent-ruby (1.3.5) sha256=813b3e37aca6df2a21a3b9f1d497f8cbab24a2b94cab325bffe65ee0f6cbebc6
|
198
193
|
connection_pool (2.5.0) sha256=233b92f8d38e038c1349ccea65dd3772727d669d6d2e71f9897c8bf5cd53ebfc
|
@@ -216,14 +211,13 @@ CHECKSUMS
|
|
216
211
|
irb (1.15.1) sha256=d9bca745ac4207a8b728a52b98b766ca909b86ff1a504bcde3d6f8c84faae890
|
217
212
|
json (2.9.1) sha256=d2bdef4644052fad91c1785d48263756fe32fcac08b96a20bb15840e96550d11
|
218
213
|
language_server-protocol (3.17.0.4) sha256=c484626478664fd13482d8180947c50a8590484b1258b99b7aedb3b69df89669
|
219
|
-
|
220
|
-
living_document (1.1.1)
|
214
|
+
living_document (2.1.0)
|
221
215
|
logger (1.6.5) sha256=c3cfe56d01656490ddd103d38b8993d73d86296adebc5f58cefc9ec03741e56b
|
222
216
|
memo_wise (1.10.0) sha256=ae40ff8e7799697ff5d59d739b8766f76be22eba69c7c8468edb42ab83c94c3f
|
223
217
|
method_source (1.1.0) sha256=181301c9c45b731b4769bc81e8860e72f9161ad7d66dd99103c9ab84f560f5c5
|
224
218
|
minitest (5.25.4) sha256=9cf2cae25ac4dfc90c988ebc3b917f53c054978b673273da1bd20bcb0778f947
|
225
219
|
parallel (1.26.3) sha256=d86babb7a2b814be9f4b81587bf0b6ce2da7d45969fab24d8ae4bf2bb4d4c7ef
|
226
|
-
parser (3.3.7.
|
220
|
+
parser (3.3.7.1) sha256=7dbe61618025519024ac72402a6677ead02099587a5538e84371b76659e6aca1
|
227
221
|
pp (0.6.2) sha256=947ec3120c6f92195f8ee8aa25a7b2c5297bb106d83b41baa02983686577b6ff
|
228
222
|
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
|
229
223
|
prism (1.3.0) sha256=b11620829831b1cb7e6c9b46c81ff8a6e36ccb3f888f164485eb7351f386273a
|
@@ -233,7 +227,6 @@ CHECKSUMS
|
|
233
227
|
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
234
228
|
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
|
235
229
|
rake (13.2.1) sha256=46cb38dae65d7d74b6020a4ac9d48afed8eb8149c040eccf0523bec91907059d
|
236
|
-
rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
|
237
230
|
rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
|
238
231
|
rdoc (6.11.0) sha256=bec66fb9b019be64f7ba7d2cd2aecb283a3a01fef23a95b33e2349c6d1aa0040
|
239
232
|
regexp_parser (2.10.0) sha256=cb6f0ddde88772cd64bff1dbbf68df66d376043fe2e66a9ef77fcb1b0c548c61
|
@@ -244,13 +237,14 @@ CHECKSUMS
|
|
244
237
|
rspec-expectations (3.13.3) sha256=0e6b5af59b900147698ea0ff80456c4f2e69cac4394fbd392fbd1ca561f66c58
|
245
238
|
rspec-mocks (3.13.2) sha256=2327335def0e1665325a9b617e3af9ae20272741d80ac550336309a7c59abdef
|
246
239
|
rspec-support (3.13.2) sha256=cea3a2463fd9b84b9dcc9685efd80ea701aa8f7b3decb3b3ce795ed67737dbec
|
247
|
-
rubocop (1.71.
|
240
|
+
rubocop (1.71.2) sha256=9a7b7501aac661a338ed7ff2a5eba78e581759e1f0d3c82362b2ca217ed3f97f
|
248
241
|
rubocop-ast (1.38.0) sha256=4fdf6792fe443a9a18acb12dbc8225d0d64cd1654e41fedb30e79c18edbb26ae
|
249
242
|
rubocop-performance (1.23.1) sha256=f22f86a795f5e6a6180aac2c6fc172534b173a068d6ed3396d6460523e051b82
|
250
243
|
rubocop-rake (0.6.0) sha256=56b6f22189af4b33d4f4e490a555c09f1281b02f4d48c3a61f6e8fe5f401d8db
|
251
244
|
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
|
252
|
-
|
253
|
-
|
245
|
+
runger_byebug (11.3.0) sha256=5728ac0a94daa88e36de256976d59e9308f67bbb8c73b3e42de7cf52de53b9aa
|
246
|
+
runger_release_assistant (2.0.0) sha256=f4f5708291eaeef1b881208f87a494877fe768739d6e96b7293fc335b28a3865
|
247
|
+
runger_style (4.3.0) sha256=543c2414626d9084fef8fd057bf561c702e395f35e7af4ee6ee403276cf60614
|
254
248
|
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
255
249
|
simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
|
256
250
|
simplecov-cobertura (2.1.0) sha256=2c6532e34df2e38a379d72cef9a05c3b16c64ce90566beebc6887801c4ad3f02
|
data/README.md
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
[](https://codecov.io/gh/davidrunger/living_document)
|
2
2
|
|
3
|
+
<p align="center">
|
4
|
+
<img src="https://david-runger-public-uploads.s3.us-east-1.amazonaws.com/living_document.gif" />
|
5
|
+
</p>
|
6
|
+
|
3
7
|
# LivingDocument
|
4
8
|
|
5
|
-
LivingDocument evaluates Ruby
|
9
|
+
LivingDocument evaluates Ruby code live and inline in your editor while you edit a Ruby file, or a Markdown file that includes Ruby code snippets. This is useful for quickly exploring ideas in Ruby code, since it can be faster and more convenient than working in IRB or running a Ruby script repeatedly as you edit it. It's also great for editing README.md documentation while ensuring the accuracy of example code snippets.
|
6
10
|
|
7
11
|
For example, if you write this in your editor...
|
8
12
|
|
@@ -32,8 +36,12 @@ In other words, the special markers `###` and `# =>` tell LivingDocument to eval
|
|
32
36
|
<!--ts-->
|
33
37
|
* [LivingDocument](#livingdocument)
|
34
38
|
* [Table of Contents](#table-of-contents)
|
39
|
+
* [Linux only <g-emoji class="g-emoji" alias="warning">⚠️</g-emoji>](#️-linux-only-️)
|
35
40
|
* [Installation](#installation)
|
36
41
|
* [Usage](#usage)
|
42
|
+
* [Editor compatibility](#editor-compatibility)
|
43
|
+
* [VS Code](#vs-code)
|
44
|
+
* [NeoVim](#neovim)
|
37
45
|
* [Markdown support](#markdown-support)
|
38
46
|
* [Time is frozen](#time-is-frozen)
|
39
47
|
* [Development](#development)
|
@@ -41,10 +49,14 @@ In other words, the special markers `###` and `# =>` tell LivingDocument to eval
|
|
41
49
|
* [License](#license)
|
42
50
|
|
43
51
|
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
|
44
|
-
<!-- Added by: david, at: Wed
|
52
|
+
<!-- Added by: david, at: Wed Feb 5 11:12:42 PM CST 2025 -->
|
45
53
|
|
46
54
|
<!--te-->
|
47
55
|
|
56
|
+
## ⚠️ Linux only ⚠️
|
57
|
+
|
58
|
+
`living_document` relies on [`rb-inotify`](https://github.com/guard/rb-inotify), which provides efficient file system event notifications using the Linux inotify API. Since inotify is exclusive to the Linux kernel, the functionality provided by `rb-inotify` cannot be replicated on other operating systems. Since `living_document` relies on `rb-inotify` for efficient file system watching, `living_document` also only works on Linux.
|
59
|
+
|
48
60
|
## Installation
|
49
61
|
|
50
62
|
```
|
@@ -93,6 +105,28 @@ puts('This is one great string!')
|
|
93
105
|
|
94
106
|
Then, edit the file and save it again. You'll see that the `# => ` comments are automatically and immediately updated to reflect your edits.
|
95
107
|
|
108
|
+
## Editor compatibility
|
109
|
+
|
110
|
+
### VS Code
|
111
|
+
|
112
|
+
LivingDocument should work with VS Code "out of the box".
|
113
|
+
|
114
|
+
### NeoVim
|
115
|
+
|
116
|
+
For LivingDocument to work with NeoVim, you will need to add config like this to your `init.lua`:
|
117
|
+
|
118
|
+
```lua
|
119
|
+
-- Auto-reload files changed outside NeoVim.
|
120
|
+
vim.opt.autoread = true
|
121
|
+
-- Preserve inodes when saving / modify files in place.
|
122
|
+
vim.opt.backupcopy = 'yes'
|
123
|
+
-- Check for changes when switching buffers, cursor idles, or NeoVim regains focus.
|
124
|
+
vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "CursorHoldI", "FocusGained" }, {
|
125
|
+
command = "if mode() != 'c' | checktime | endif",
|
126
|
+
pattern = { "*" },
|
127
|
+
})
|
128
|
+
```
|
129
|
+
|
96
130
|
## Markdown support
|
97
131
|
|
98
132
|
LivingDocument can also handle Markdown code, which is especially convenient when developing
|
data/exe/livdoc
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
|
-
require '
|
5
|
+
require 'io/console'
|
6
6
|
require 'optparse'
|
7
|
+
require 'rb-inotify'
|
7
8
|
|
8
9
|
require_relative '../lib/living_document.rb'
|
9
10
|
|
@@ -15,17 +16,44 @@ end
|
|
15
16
|
parser.parse!
|
16
17
|
|
17
18
|
# rubocop:disable Style/TopLevelMethodDefinition
|
18
|
-
def evaluate_code_and_update_source_file(file_path)
|
19
|
-
|
19
|
+
def evaluate_code_and_update_source_file(file_path, evaluation_reason:)
|
20
|
+
print("#{Time.now.iso8601} #{evaluation_reason} ... ")
|
21
|
+
# NOTE: This sleep seems to be necessary to interact reliably with VS Code.
|
22
|
+
sleep(0.015)
|
20
23
|
code_in_file = File.read(file_path)
|
24
|
+
|
25
|
+
print('running code ... ')
|
21
26
|
code_to_write =
|
22
27
|
LivingDocument::DocumentEvaluator.new(
|
23
28
|
document: code_in_file,
|
24
29
|
).evaluated_document
|
25
30
|
|
26
|
-
|
27
|
-
|
31
|
+
# NOTE: This sleep seems to be necessary to interact reliably with VS Code.
|
32
|
+
sleep(0.015)
|
33
|
+
print('writing file ... ')
|
28
34
|
File.write(file_path, code_to_write)
|
35
|
+
|
36
|
+
puts('waiting for changes.')
|
37
|
+
end
|
38
|
+
|
39
|
+
def ask_to_create_file_if_needed(expanded_path)
|
40
|
+
if !File.exist?(expanded_path)
|
41
|
+
puts(<<~QUESTION)
|
42
|
+
The target file (#{expanded_path}) does not exist.
|
43
|
+
Would you like living_document to create it? [y]n
|
44
|
+
QUESTION
|
45
|
+
|
46
|
+
case $stdin.getch
|
47
|
+
when 'n', "\u0003" # Ctrl-C
|
48
|
+
puts('Okay, then, exiting.')
|
49
|
+
exit(0)
|
50
|
+
when 'y', "\r"
|
51
|
+
FileUtils.touch(expanded_path)
|
52
|
+
else
|
53
|
+
puts("\nThat's not an option.\n\n")
|
54
|
+
ask_to_create_file_if_needed(expanded_path)
|
55
|
+
end
|
56
|
+
end
|
29
57
|
end
|
30
58
|
# rubocop:enable Style/TopLevelMethodDefinition
|
31
59
|
|
@@ -36,27 +64,38 @@ if file_path.nil?
|
|
36
64
|
exit(1)
|
37
65
|
end
|
38
66
|
|
67
|
+
expanded_path = File.expand_path(file_path)
|
68
|
+
|
69
|
+
ask_to_create_file_if_needed(expanded_path)
|
70
|
+
|
71
|
+
if system('[ -n "$EDITOR" ]')
|
72
|
+
system("$EDITOR #{expanded_path}")
|
73
|
+
end
|
74
|
+
|
75
|
+
notifier = INotify::Notifier.new
|
39
76
|
last_file_update = Time.now
|
40
|
-
listener =
|
41
|
-
Listen.to(Dir.pwd, only: /\A#{Regexp.escape(file_path)}\z/) do |_modified, _added, _removed|
|
42
|
-
# Don't enter infinitely recursive loop, since the code below triggers file updates.
|
43
|
-
# After file has been updated, wait at least 0.5 seconds before listener processes again.
|
44
|
-
next if (Time.now - last_file_update) < 0.5
|
45
77
|
|
46
|
-
|
78
|
+
notifier.watch(expanded_path, :modify) do |_event|
|
79
|
+
# Don't enter infinitely recursive loop, since the code below triggers file updates.
|
80
|
+
# After file has been updated, wait at least 0.2 seconds before listener processes again.
|
81
|
+
next if (Time.now - last_file_update) < 0.2
|
47
82
|
|
48
|
-
|
49
|
-
end
|
83
|
+
evaluate_code_and_update_source_file(expanded_path, evaluation_reason: 'Detected file change')
|
50
84
|
|
51
|
-
|
52
|
-
|
53
|
-
evaluate_code_and_update_source_file(file_path)
|
54
|
-
puts('Waiting for file changes...')
|
85
|
+
last_file_update = Time.now
|
86
|
+
end
|
55
87
|
|
56
88
|
at_exit do
|
57
89
|
print('Stopping listener ... ')
|
58
|
-
|
90
|
+
notifier.close
|
59
91
|
puts('done.')
|
60
92
|
end
|
61
93
|
|
62
|
-
|
94
|
+
system('clear')
|
95
|
+
evaluate_code_and_update_source_file(expanded_path, evaluation_reason: 'Launching')
|
96
|
+
|
97
|
+
begin
|
98
|
+
notifier.run
|
99
|
+
rescue Interrupt
|
100
|
+
# Exit gracefully, having run `at_exit` block.
|
101
|
+
end
|
@@ -13,6 +13,8 @@ class LivingDocument::CodeEvaluator
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def evaluated_code
|
16
|
+
save_original_stdout
|
17
|
+
|
16
18
|
Timecop.freeze do
|
17
19
|
printed_code_segments.each_with_index do |printed_code_segment, index|
|
18
20
|
$printed_output = ''
|
@@ -20,34 +22,45 @@ class LivingDocument::CodeEvaluator
|
|
20
22
|
|
21
23
|
result =
|
22
24
|
begin
|
23
|
-
#
|
24
|
-
new_namespace.
|
25
|
+
# We need to namespace any constants that would otherwise leak and persist globally.
|
26
|
+
new_namespace.
|
27
|
+
instance_eval(code_to_eval(index)).
|
28
|
+
inspect.
|
29
|
+
squish.
|
30
|
+
then do |evaluated_result|
|
31
|
+
if newly_printed_output.present?
|
32
|
+
result_for_printed_output
|
33
|
+
else
|
34
|
+
formatted_evaluated_result(evaluated_result)
|
35
|
+
end
|
36
|
+
end
|
25
37
|
rescue => error
|
26
|
-
# Comment these lines back in for debugging:
|
27
|
-
# puts("ERROR: #{error.class}:#{error.message}")
|
28
|
-
# puts(error.backtrace)
|
29
38
|
@known_erroring_segment_indexes << index
|
39
|
+
|
30
40
|
"raises #{error.class} (#{error.message})"
|
31
41
|
end
|
32
42
|
|
33
|
-
|
34
|
-
result = result_for_printed_output
|
35
|
-
elsif result.include?('\"')
|
36
|
-
result = "'#{result.gsub('\"', '"')[1...-1]}'"
|
37
|
-
end
|
38
|
-
remember_printed_objects
|
43
|
+
remember_printed_output
|
39
44
|
|
40
45
|
swap_in_evaluated_code(printed_code_segment, result)
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
|
-
restore_original_stdout
|
45
|
-
|
46
49
|
@code
|
50
|
+
ensure
|
51
|
+
restore_original_stdout
|
47
52
|
end
|
48
53
|
|
49
54
|
private
|
50
55
|
|
56
|
+
def formatted_evaluated_result(evaluated_result)
|
57
|
+
if evaluated_result.include?('\"') && !evaluated_result.include?("'")
|
58
|
+
"'#{evaluated_result.gsub('\"', '"')[1...-1]}'"
|
59
|
+
else
|
60
|
+
evaluated_result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
51
64
|
def result_for_printed_output
|
52
65
|
if newly_printed_output[0..-2].include?("\n")
|
53
66
|
%(prints:\n#{commented_output(newly_printed_output)})
|
@@ -64,8 +77,11 @@ class LivingDocument::CodeEvaluator
|
|
64
77
|
COMMENTED_OUTPUT
|
65
78
|
end
|
66
79
|
|
67
|
-
def
|
80
|
+
def save_original_stdout
|
68
81
|
@original_stdout = $stdout
|
82
|
+
end
|
83
|
+
|
84
|
+
def set_up_capturing_stdout
|
69
85
|
$stdout = StringIO.new
|
70
86
|
end
|
71
87
|
|
@@ -76,7 +92,7 @@ class LivingDocument::CodeEvaluator
|
|
76
92
|
end
|
77
93
|
|
78
94
|
def code_segments_to_eval(current_index)
|
79
|
-
|
95
|
+
printed_code_segments.values_at(*indexes_to_eval(current_index))
|
80
96
|
end
|
81
97
|
|
82
98
|
def code_to_eval(current_index)
|
@@ -106,11 +122,7 @@ class LivingDocument::CodeEvaluator
|
|
106
122
|
@code.scan(/(?:(?!###|# =>).)*(?:###|# =>)[^\n]*\s*/mi)
|
107
123
|
end
|
108
124
|
|
109
|
-
def
|
110
|
-
printed_code_segments.values_at(*indexes_to_eval(current_index))
|
111
|
-
end
|
112
|
-
|
113
|
-
def remember_printed_objects
|
125
|
+
def remember_printed_output
|
114
126
|
$printed_output_last_run = $printed_output
|
115
127
|
end
|
116
128
|
|
data/lib/living_document.rb
CHANGED
data/living_document.gemspec
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'lib/living_document/platform_check'
|
3
4
|
require_relative 'lib/living_document/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |spec|
|
7
|
+
LivingDocument.check_platform!
|
8
|
+
|
6
9
|
spec.name = 'living_document'
|
7
10
|
spec.version = LivingDocument::VERSION
|
8
11
|
spec.authors = ['David Runger']
|
@@ -31,7 +34,7 @@ Gem::Specification.new do |spec|
|
|
31
34
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
35
|
|
33
36
|
spec.add_dependency('activesupport', '>= 6')
|
34
|
-
spec.add_dependency('listen', '>= 3.2')
|
35
37
|
spec.add_dependency('memo_wise', '>= 1.7')
|
38
|
+
spec.add_dependency('rb-inotify', '>= 0.11.1')
|
36
39
|
spec.add_dependency('timecop', '>= 0.9.10')
|
37
40
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: living_document
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Runger
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-02-06 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activesupport
|
@@ -24,33 +24,33 @@ dependencies:
|
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: '6'
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
|
-
name:
|
27
|
+
name: memo_wise
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '1.7'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
39
|
+
version: '1.7'
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
|
-
name:
|
41
|
+
name: rb-inotify
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: 0.11.1
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
53
|
+
version: 0.11.1
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: timecop
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- lib/living_document.rb
|
98
98
|
- lib/living_document/code_evaluator.rb
|
99
99
|
- lib/living_document/document_evaluator.rb
|
100
|
+
- lib/living_document/platform_check.rb
|
100
101
|
- lib/living_document/version.rb
|
101
102
|
- living_document.gemspec
|
102
103
|
homepage: https://github.com/davidrunger/living_document
|