living_document 1.0.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 +7 -0
- data/.github/dependabot.yml +12 -0
- data/.github/workflows/ruby.yml +33 -0
- data/.gitignore +11 -0
- data/.release_assistant.yml +3 -0
- data/.rubocop.yml +4 -0
- data/.ruby-version +1 -0
- data/.runger-config.yml +1 -0
- data/CHANGELOG.md +80 -0
- data/Gemfile +33 -0
- data/Gemfile.lock +271 -0
- data/LICENSE.txt +21 -0
- data/README.md +180 -0
- data/Rakefile +3 -0
- data/bin/_guard-core +28 -0
- data/bin/console +7 -0
- data/bin/githooks/pre-push +9 -0
- data/bin/guard +28 -0
- data/bin/release +28 -0
- data/bin/rspec +28 -0
- data/bin/rubocop +30 -0
- data/exe/livdoc +54 -0
- data/lib/living_document/code_evaluator.rb +118 -0
- data/lib/living_document/document_evaluator.rb +41 -0
- data/lib/living_document/version.rb +5 -0
- data/lib/living_document.rb +10 -0
- data/living_document.gemspec +37 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5333d18700fb6f434f873c15fddd87f2e91fd811efe23125ae017022f84f35dc
|
4
|
+
data.tar.gz: 8c181f2f67c7dd4b9f08284c87a65d04e371c757362aa366518f1bbcdeec1b70
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7bdd09efd21f2166bbb240ac8a7ac6899279c180e9a23202caea1114ef02f776bfe3a9dece7ecbbd1897e9b07522493bf813b41afa0ec68fc593841613d7a2a3
|
7
|
+
data.tar.gz: eebf8135e7cab06726572129aa3db97e89a3d7183ac6cf543b10b1ff3e3df685e2159fb404cb5610994d7ebdf1de16953096984d92030c78fbc54af3eb2ee9c4
|
@@ -0,0 +1,33 @@
|
|
1
|
+
name: Run RuboCop and RSpec
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
branches:
|
6
|
+
- '*'
|
7
|
+
push:
|
8
|
+
branches:
|
9
|
+
- main
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
build:
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v4
|
16
|
+
- uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
bundler-cache: true
|
19
|
+
- name: Lint with RuboCop
|
20
|
+
run: bin/rubocop --format clang
|
21
|
+
- name: Run RSpec tests
|
22
|
+
run: bin/rspec --format progress --force-color
|
23
|
+
- name: Ensure alpha version
|
24
|
+
run: grep alpha $(find . -type f -name version.rb)
|
25
|
+
- name: Ensure no git diff
|
26
|
+
run: git diff --exit-code && git diff-index --quiet --cached HEAD
|
27
|
+
- name: Ensure "## Unreleased" is in CHANGELOG.md
|
28
|
+
run: grep "^## Unreleased" CHANGELOG.md
|
29
|
+
- name: Upload Code Coverage
|
30
|
+
uses: codecov/codecov-action@v4
|
31
|
+
with:
|
32
|
+
directory: tmp/simple_cov
|
33
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.4.1
|
data/.runger-config.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
expected-num-github-checks: 3
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
## v1.0.0 (2025-01-29)
|
2
|
+
- **BREAKING:** Remove web server functionality.
|
3
|
+
- **BREAKING:** Freeze time with `timecop` when executing code.
|
4
|
+
- **BREAKING:** Make target file customizable (and require a target argument for the CLI).
|
5
|
+
- Release via RubyGems.
|
6
|
+
|
7
|
+
## v0.8.0 (2024-12-10)
|
8
|
+
- Remove upper bounds on versions for all dependencies.
|
9
|
+
|
10
|
+
## v0.7.0 (2024-06-28)
|
11
|
+
- Enforce only major and minor parts of required Ruby version (loosening the required Ruby version from 3.3.3 to 3.3.0)
|
12
|
+
|
13
|
+
## v0.6.0 (2024-06-15)
|
14
|
+
- Renamed primary branch from `master` to `main`
|
15
|
+
|
16
|
+
## v0.5.4 (2023-05-30)
|
17
|
+
### Changed
|
18
|
+
- Update dependencies
|
19
|
+
|
20
|
+
## v0.5.3 (2023-05-30)
|
21
|
+
### Changed
|
22
|
+
- Move from Memoist to MemoWise
|
23
|
+
|
24
|
+
## v0.5.2 (2021-02-13)
|
25
|
+
### Fixed
|
26
|
+
- Actually fix "uninitialized constant StringIO" error when running `livdoc` executable
|
27
|
+
|
28
|
+
## v0.5.1 (2021-02-13)
|
29
|
+
### Fixed
|
30
|
+
- Fix "uninitialized constant StringIO" error when running `livdoc` executable
|
31
|
+
|
32
|
+
## v0.5.0 (2021-02-06)
|
33
|
+
### Added
|
34
|
+
- Support logging multiple printed outputs
|
35
|
+
- Automatically monkeypatch `puts` to capture output
|
36
|
+
|
37
|
+
## v0.4.0 (2021-02-04)
|
38
|
+
### Added
|
39
|
+
- Render markdown preview next to web-based editor
|
40
|
+
|
41
|
+
## v0.3.0 (2021-02-04)
|
42
|
+
### Added
|
43
|
+
- Add support for evaluating Ruby code blocks within Markdown documents
|
44
|
+
|
45
|
+
## v0.2.2 (2021-02-03)
|
46
|
+
### Added
|
47
|
+
- Add ability to toggle the "Frontmatter" section in the web editor
|
48
|
+
|
49
|
+
### Internal
|
50
|
+
- Set up RSpec testing
|
51
|
+
- Add some tests for `CodeEvaluator`
|
52
|
+
- Add test coverage reporting (via `codecov` and `simplecov`)
|
53
|
+
|
54
|
+
## v0.2.1 (2021-02-03)
|
55
|
+
### Fixed
|
56
|
+
- Run `livdocweb` with Ruby (not bash)
|
57
|
+
|
58
|
+
## v0.2.0 (2021-02-03)
|
59
|
+
### Added
|
60
|
+
- Add web-based editor
|
61
|
+
|
62
|
+
## v0.1.4 (2021-01-26)
|
63
|
+
### Dependencies
|
64
|
+
- Bump `release_assistant` to `0.1.1.alpha`
|
65
|
+
|
66
|
+
## v0.1.3 (2021-01-26)
|
67
|
+
### Internal
|
68
|
+
- Move CI from Travis to GitHub Actions
|
69
|
+
- Use `release_assistant` gem to manage the release process
|
70
|
+
|
71
|
+
## v0.1.2 (2021-01-07)
|
72
|
+
### Internal
|
73
|
+
- Added `rubocop-rake` gem
|
74
|
+
|
75
|
+
## v0.1.1 (2020-07-02)
|
76
|
+
### Internal
|
77
|
+
- Source Rubocop rules/config from `runger_style` gem
|
78
|
+
|
79
|
+
## v0.1.0 (2020-06-20)
|
80
|
+
- Initial release of `living_document`!
|
data/Gemfile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
ruby file: '.ruby-version'
|
4
|
+
|
5
|
+
source 'https://rubygems.org'
|
6
|
+
|
7
|
+
# Specify your gem's dependencies in living_document.gemspec
|
8
|
+
gemspec
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem 'amazing_print'
|
12
|
+
# Remove if/when byebug brings in this dependency for us.
|
13
|
+
gem 'irb'
|
14
|
+
gem 'pry'
|
15
|
+
# Go back to upstream if/when https://github.com/deivid-rodriguez/pry-byebug/pull/ 428 is merged.
|
16
|
+
gem 'pry-byebug', github: 'davidrunger/pry-byebug'
|
17
|
+
gem 'rake'
|
18
|
+
# Remove if/when byebug brings in this dependency for us.
|
19
|
+
gem 'reline'
|
20
|
+
gem 'rubocop', require: false
|
21
|
+
gem 'rubocop-performance', require: false
|
22
|
+
gem 'rubocop-rake', require: false
|
23
|
+
gem 'runger_style', require: false
|
24
|
+
end
|
25
|
+
|
26
|
+
group :development do
|
27
|
+
gem 'runger_release_assistant', require: false
|
28
|
+
end
|
29
|
+
|
30
|
+
group :test do
|
31
|
+
gem 'rspec'
|
32
|
+
gem 'simplecov-cobertura', require: false
|
33
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,271 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/davidrunger/pry-byebug.git
|
3
|
+
revision: f6f73023ba081630ddee32ae4399fb31706f074f
|
4
|
+
specs:
|
5
|
+
pry-byebug (3.10.1)
|
6
|
+
byebug (>= 11.0)
|
7
|
+
pry (>= 0.13)
|
8
|
+
|
9
|
+
PATH
|
10
|
+
remote: .
|
11
|
+
specs:
|
12
|
+
living_document (1.0.0)
|
13
|
+
activesupport (>= 6)
|
14
|
+
listen (>= 3.2)
|
15
|
+
memo_wise (>= 1.7)
|
16
|
+
timecop (>= 0.9.10)
|
17
|
+
|
18
|
+
GEM
|
19
|
+
remote: https://rubygems.org/
|
20
|
+
specs:
|
21
|
+
activesupport (8.0.1)
|
22
|
+
base64
|
23
|
+
benchmark (>= 0.3)
|
24
|
+
bigdecimal
|
25
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
26
|
+
connection_pool (>= 2.2.5)
|
27
|
+
drb
|
28
|
+
i18n (>= 1.6, < 2)
|
29
|
+
logger (>= 1.4.2)
|
30
|
+
minitest (>= 5.1)
|
31
|
+
securerandom (>= 0.3)
|
32
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
33
|
+
uri (>= 0.13.1)
|
34
|
+
amazing_print (1.7.2)
|
35
|
+
ast (2.4.2)
|
36
|
+
base64 (0.2.0)
|
37
|
+
benchmark (0.4.0)
|
38
|
+
bigdecimal (3.1.9)
|
39
|
+
byebug (11.1.3)
|
40
|
+
coderay (1.1.3)
|
41
|
+
concurrent-ruby (1.3.5)
|
42
|
+
connection_pool (2.5.0)
|
43
|
+
date (3.4.1)
|
44
|
+
diff-lcs (1.5.1)
|
45
|
+
docile (1.4.1)
|
46
|
+
drb (2.2.1)
|
47
|
+
ffi (1.17.1)
|
48
|
+
ffi (1.17.1-aarch64-linux-gnu)
|
49
|
+
ffi (1.17.1-aarch64-linux-musl)
|
50
|
+
ffi (1.17.1-arm-linux-gnu)
|
51
|
+
ffi (1.17.1-arm-linux-musl)
|
52
|
+
ffi (1.17.1-arm64-darwin)
|
53
|
+
ffi (1.17.1-x86-linux-gnu)
|
54
|
+
ffi (1.17.1-x86-linux-musl)
|
55
|
+
ffi (1.17.1-x86_64-darwin)
|
56
|
+
ffi (1.17.1-x86_64-linux-gnu)
|
57
|
+
ffi (1.17.1-x86_64-linux-musl)
|
58
|
+
i18n (1.14.7)
|
59
|
+
concurrent-ruby (~> 1.0)
|
60
|
+
io-console (0.8.0)
|
61
|
+
irb (1.15.1)
|
62
|
+
pp (>= 0.6.0)
|
63
|
+
rdoc (>= 4.0.0)
|
64
|
+
reline (>= 0.4.2)
|
65
|
+
json (2.9.1)
|
66
|
+
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
|
+
logger (1.6.5)
|
71
|
+
memo_wise (1.10.0)
|
72
|
+
method_source (1.1.0)
|
73
|
+
minitest (5.25.4)
|
74
|
+
parallel (1.26.3)
|
75
|
+
parser (3.3.7.0)
|
76
|
+
ast (~> 2.4.1)
|
77
|
+
racc
|
78
|
+
pp (0.6.2)
|
79
|
+
prettyprint
|
80
|
+
prettyprint (0.2.0)
|
81
|
+
prism (1.3.0)
|
82
|
+
pry (0.15.2)
|
83
|
+
coderay (~> 1.1)
|
84
|
+
method_source (~> 1.0)
|
85
|
+
psych (5.2.3)
|
86
|
+
date
|
87
|
+
stringio
|
88
|
+
racc (1.8.1)
|
89
|
+
rainbow (3.1.1)
|
90
|
+
rake (13.2.1)
|
91
|
+
rb-fsevent (0.11.2)
|
92
|
+
rb-inotify (0.11.1)
|
93
|
+
ffi (~> 1.0)
|
94
|
+
rdoc (6.11.0)
|
95
|
+
psych (>= 4.0.0)
|
96
|
+
regexp_parser (2.10.0)
|
97
|
+
reline (0.6.0)
|
98
|
+
io-console (~> 0.5)
|
99
|
+
rexml (3.4.0)
|
100
|
+
rspec (3.13.0)
|
101
|
+
rspec-core (~> 3.13.0)
|
102
|
+
rspec-expectations (~> 3.13.0)
|
103
|
+
rspec-mocks (~> 3.13.0)
|
104
|
+
rspec-core (3.13.2)
|
105
|
+
rspec-support (~> 3.13.0)
|
106
|
+
rspec-expectations (3.13.3)
|
107
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
108
|
+
rspec-support (~> 3.13.0)
|
109
|
+
rspec-mocks (3.13.2)
|
110
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
111
|
+
rspec-support (~> 3.13.0)
|
112
|
+
rspec-support (3.13.2)
|
113
|
+
rubocop (1.71.0)
|
114
|
+
json (~> 2.3)
|
115
|
+
language_server-protocol (>= 3.17.0)
|
116
|
+
parallel (~> 1.10)
|
117
|
+
parser (>= 3.3.0.2)
|
118
|
+
rainbow (>= 2.2.2, < 4.0)
|
119
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
120
|
+
rubocop-ast (>= 1.36.2, < 2.0)
|
121
|
+
ruby-progressbar (~> 1.7)
|
122
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
123
|
+
rubocop-ast (1.38.0)
|
124
|
+
parser (>= 3.3.1.0)
|
125
|
+
rubocop-performance (1.23.1)
|
126
|
+
rubocop (>= 1.48.1, < 2.0)
|
127
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
128
|
+
rubocop-rake (0.6.0)
|
129
|
+
rubocop (~> 1.0)
|
130
|
+
ruby-progressbar (1.13.0)
|
131
|
+
runger_release_assistant (0.14.0)
|
132
|
+
activesupport (>= 6)
|
133
|
+
memo_wise (>= 1.7)
|
134
|
+
rainbow (>= 3.0)
|
135
|
+
slop (~> 4.8)
|
136
|
+
runger_style (4.2.2)
|
137
|
+
prism (>= 0.24.0)
|
138
|
+
rubocop (>= 1.68.0)
|
139
|
+
securerandom (0.4.1)
|
140
|
+
simplecov (0.22.0)
|
141
|
+
docile (~> 1.1)
|
142
|
+
simplecov-html (~> 0.11)
|
143
|
+
simplecov_json_formatter (~> 0.1)
|
144
|
+
simplecov-cobertura (2.1.0)
|
145
|
+
rexml
|
146
|
+
simplecov (~> 0.19)
|
147
|
+
simplecov-html (0.13.1)
|
148
|
+
simplecov_json_formatter (0.1.4)
|
149
|
+
slop (4.10.1)
|
150
|
+
stringio (3.1.2)
|
151
|
+
timecop (0.9.10)
|
152
|
+
tzinfo (2.0.6)
|
153
|
+
concurrent-ruby (~> 1.0)
|
154
|
+
unicode-display_width (3.1.4)
|
155
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
156
|
+
unicode-emoji (4.0.4)
|
157
|
+
uri (1.0.2)
|
158
|
+
|
159
|
+
PLATFORMS
|
160
|
+
aarch64-linux-gnu
|
161
|
+
aarch64-linux-musl
|
162
|
+
arm-linux-gnu
|
163
|
+
arm-linux-musl
|
164
|
+
arm64-darwin
|
165
|
+
ruby
|
166
|
+
x86-linux-gnu
|
167
|
+
x86-linux-musl
|
168
|
+
x86_64-darwin
|
169
|
+
x86_64-linux-gnu
|
170
|
+
x86_64-linux-musl
|
171
|
+
|
172
|
+
DEPENDENCIES
|
173
|
+
amazing_print
|
174
|
+
irb
|
175
|
+
living_document!
|
176
|
+
pry
|
177
|
+
pry-byebug!
|
178
|
+
rake
|
179
|
+
reline
|
180
|
+
rspec
|
181
|
+
rubocop
|
182
|
+
rubocop-performance
|
183
|
+
rubocop-rake
|
184
|
+
runger_release_assistant
|
185
|
+
runger_style
|
186
|
+
simplecov-cobertura
|
187
|
+
|
188
|
+
CHECKSUMS
|
189
|
+
activesupport (8.0.1) sha256=fd5bc74641c24ac3541055c2879789198ff42adee3e39c2933289ba008912e37
|
190
|
+
amazing_print (1.7.2) sha256=c89a1dfe4f8508c1e780871d51b8786efd100f625201f6e1d18a0d4dedaac702
|
191
|
+
ast (2.4.2) sha256=1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12
|
192
|
+
base64 (0.2.0) sha256=0f25e9b21a02a0cc0cea8ef92b2041035d39350946e8789c562b2d1a3da01507
|
193
|
+
benchmark (0.4.0) sha256=0f12f8c495545e3710c3e4f0480f63f06b4c842cc94cec7f33a956f5180e874a
|
194
|
+
bigdecimal (3.1.9) sha256=2ffc742031521ad69c2dfc815a98e426a230a3d22aeac1995826a75dabfad8cc
|
195
|
+
byebug (11.1.3) sha256=2485944d2bb21283c593d562f9ae1019bf80002143cc3a255aaffd4e9cf4a35b
|
196
|
+
coderay (1.1.3) sha256=dc530018a4684512f8f38143cd2a096c9f02a1fc2459edcfe534787a7fc77d4b
|
197
|
+
concurrent-ruby (1.3.5) sha256=813b3e37aca6df2a21a3b9f1d497f8cbab24a2b94cab325bffe65ee0f6cbebc6
|
198
|
+
connection_pool (2.5.0) sha256=233b92f8d38e038c1349ccea65dd3772727d669d6d2e71f9897c8bf5cd53ebfc
|
199
|
+
date (3.4.1) sha256=bf268e14ef7158009bfeaec40b5fa3c7271906e88b196d958a89d4b408abe64f
|
200
|
+
diff-lcs (1.5.1) sha256=273223dfb40685548436d32b4733aa67351769c7dea621da7d9dd4813e63ddfe
|
201
|
+
docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
|
202
|
+
drb (2.2.1) sha256=e9d472bf785f558b96b25358bae115646da0dbfd45107ad858b0bc0d935cb340
|
203
|
+
ffi (1.17.1) sha256=26f6b0dbd1101e6ffc09d3ca640b2a21840cc52731ad8a7ded9fb89e5fb0fc39
|
204
|
+
ffi (1.17.1-aarch64-linux-gnu) sha256=c5d22cb545a3a691d46060f1343c461d1a8d38c3fd71b96b4cbbe6906bf1fd38
|
205
|
+
ffi (1.17.1-aarch64-linux-musl) sha256=88b9d6ae905d21142df27c94bb300042c1aae41b67291885f600eaad16326b1d
|
206
|
+
ffi (1.17.1-arm-linux-gnu) sha256=fe14f5ece94082f3b0e651a09008113281f2764e7ea95f522b64e2fe32e11504
|
207
|
+
ffi (1.17.1-arm-linux-musl) sha256=df14927ca7bd9095148a7d1938bb762bbf189d190cf25d9547395ec7acc198a0
|
208
|
+
ffi (1.17.1-arm64-darwin) sha256=a8e04f79d375742c54ee7f9fff4b4022b87200a4ec0eb082128d3b6559e67b4d
|
209
|
+
ffi (1.17.1-x86-linux-gnu) sha256=01411c78cb3cff3c88cf67b2a7b24534e9b1638253d88581fef44c2083f6a174
|
210
|
+
ffi (1.17.1-x86-linux-musl) sha256=02bcc7bbcff71e021ef05f43469f7c5074ab3422e415b287001bd890c9cbb1c6
|
211
|
+
ffi (1.17.1-x86_64-darwin) sha256=0036199c290462dd7f03bc22933644c1685b7834a21788062bd5df48c72aa7a6
|
212
|
+
ffi (1.17.1-x86_64-linux-gnu) sha256=8c0ade2a5d19f3672bccfe3b58e016ae5f159e3e2e741c856db87fcf07c903d0
|
213
|
+
ffi (1.17.1-x86_64-linux-musl) sha256=3a343086820c96d6fbea4a5ef807fb69105b2b8174678f103b3db210c3f78401
|
214
|
+
i18n (1.14.7) sha256=ceba573f8138ff2c0915427f1fc5bdf4aa3ab8ae88c8ce255eb3ecf0a11a5d0f
|
215
|
+
io-console (0.8.0) sha256=cd6a9facbc69871d69b2cb8b926fc6ea7ef06f06e505e81a64f14a470fddefa2
|
216
|
+
irb (1.15.1) sha256=d9bca745ac4207a8b728a52b98b766ca909b86ff1a504bcde3d6f8c84faae890
|
217
|
+
json (2.9.1) sha256=d2bdef4644052fad91c1785d48263756fe32fcac08b96a20bb15840e96550d11
|
218
|
+
language_server-protocol (3.17.0.4) sha256=c484626478664fd13482d8180947c50a8590484b1258b99b7aedb3b69df89669
|
219
|
+
listen (3.9.0) sha256=db9e4424e0e5834480385197c139cb6b0ae0ef28cc13310cfd1ca78377d59c67
|
220
|
+
living_document (1.0.0)
|
221
|
+
logger (1.6.5) sha256=c3cfe56d01656490ddd103d38b8993d73d86296adebc5f58cefc9ec03741e56b
|
222
|
+
memo_wise (1.10.0) sha256=ae40ff8e7799697ff5d59d739b8766f76be22eba69c7c8468edb42ab83c94c3f
|
223
|
+
method_source (1.1.0) sha256=181301c9c45b731b4769bc81e8860e72f9161ad7d66dd99103c9ab84f560f5c5
|
224
|
+
minitest (5.25.4) sha256=9cf2cae25ac4dfc90c988ebc3b917f53c054978b673273da1bd20bcb0778f947
|
225
|
+
parallel (1.26.3) sha256=d86babb7a2b814be9f4b81587bf0b6ce2da7d45969fab24d8ae4bf2bb4d4c7ef
|
226
|
+
parser (3.3.7.0) sha256=7449011771e3e7881297859b849de26a6f4fccd515bece9520a87e7d2116119b
|
227
|
+
pp (0.6.2) sha256=947ec3120c6f92195f8ee8aa25a7b2c5297bb106d83b41baa02983686577b6ff
|
228
|
+
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
|
229
|
+
prism (1.3.0) sha256=b11620829831b1cb7e6c9b46c81ff8a6e36ccb3f888f164485eb7351f386273a
|
230
|
+
pry (0.15.2) sha256=12d54b8640d3fa29c9211dd4ffb08f3fd8bf7a4fd9b5a73ce5b59c8709385b6b
|
231
|
+
pry-byebug (3.10.1)
|
232
|
+
psych (5.2.3) sha256=84a54bb952d14604fea22d99938348814678782f58b12648fcdfa4d2fce859ee
|
233
|
+
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
234
|
+
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
|
235
|
+
rake (13.2.1) sha256=46cb38dae65d7d74b6020a4ac9d48afed8eb8149c040eccf0523bec91907059d
|
236
|
+
rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
|
237
|
+
rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
|
238
|
+
rdoc (6.11.0) sha256=bec66fb9b019be64f7ba7d2cd2aecb283a3a01fef23a95b33e2349c6d1aa0040
|
239
|
+
regexp_parser (2.10.0) sha256=cb6f0ddde88772cd64bff1dbbf68df66d376043fe2e66a9ef77fcb1b0c548c61
|
240
|
+
reline (0.6.0) sha256=57620375dcbe56ec09bac7192bfb7460c716bbf0054dc94345ecaa5438e539d2
|
241
|
+
rexml (3.4.0) sha256=efbea1efba7fa151158e0ee1e643525834da2d8eb4cf744aa68f6480bc9804b2
|
242
|
+
rspec (3.13.0) sha256=d490914ac1d5a5a64a0e1400c1d54ddd2a501324d703b8cfe83f458337bab993
|
243
|
+
rspec-core (3.13.2) sha256=94fbda6e4738e478f1c7532b7cc241272fcdc8b9eac03a97338b1122e4573300
|
244
|
+
rspec-expectations (3.13.3) sha256=0e6b5af59b900147698ea0ff80456c4f2e69cac4394fbd392fbd1ca561f66c58
|
245
|
+
rspec-mocks (3.13.2) sha256=2327335def0e1665325a9b617e3af9ae20272741d80ac550336309a7c59abdef
|
246
|
+
rspec-support (3.13.2) sha256=cea3a2463fd9b84b9dcc9685efd80ea701aa8f7b3decb3b3ce795ed67737dbec
|
247
|
+
rubocop (1.71.0) sha256=e19679efd447346ac476122313d3788ae23c38214790bcf660e984c747608bf0
|
248
|
+
rubocop-ast (1.38.0) sha256=4fdf6792fe443a9a18acb12dbc8225d0d64cd1654e41fedb30e79c18edbb26ae
|
249
|
+
rubocop-performance (1.23.1) sha256=f22f86a795f5e6a6180aac2c6fc172534b173a068d6ed3396d6460523e051b82
|
250
|
+
rubocop-rake (0.6.0) sha256=56b6f22189af4b33d4f4e490a555c09f1281b02f4d48c3a61f6e8fe5f401d8db
|
251
|
+
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
|
252
|
+
runger_release_assistant (0.14.0) sha256=7abc5eb1e0f63d8d611691bc21698d2b3b8f148a5f47cacd8dd32c21d16ee9be
|
253
|
+
runger_style (4.2.2) sha256=23bb4c2b8875d79113f72179a7e4ad96bd5ecde8d7a54bd18f4e60c2ab65dd64
|
254
|
+
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
255
|
+
simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
|
256
|
+
simplecov-cobertura (2.1.0) sha256=2c6532e34df2e38a379d72cef9a05c3b16c64ce90566beebc6887801c4ad3f02
|
257
|
+
simplecov-html (0.13.1) sha256=5dab0b7ee612e60e9887ad57693832fdf4695b4c0c859eaea5f95c18791ef10b
|
258
|
+
simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
|
259
|
+
slop (4.10.1) sha256=844322b5ffcf17ed4815fdb173b04a20dd82b4fd93e3744c88c8fafea696d9c7
|
260
|
+
stringio (3.1.2) sha256=204f1828f85cdb39d57cac4abc6dc44b04505a223f131587f2e20ae3729ba131
|
261
|
+
timecop (0.9.10) sha256=12ba45ce57cdcf6b1043cb6cdffa6381fd89ce10d369c28a7f6f04dc1b0cd8eb
|
262
|
+
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
|
263
|
+
unicode-display_width (3.1.4) sha256=8caf2af1c0f2f07ec89ef9e18c7d88c2790e217c482bfc78aaa65eadd5415ac1
|
264
|
+
unicode-emoji (4.0.4) sha256=2c2c4ef7f353e5809497126285a50b23056cc6e61b64433764a35eff6c36532a
|
265
|
+
uri (1.0.2) sha256=b303504ceb7e5905771fa7fa14b649652fa949df18b5880d69cfb12494791e27
|
266
|
+
|
267
|
+
RUBY VERSION
|
268
|
+
ruby 3.4.1p0
|
269
|
+
|
270
|
+
BUNDLED WITH
|
271
|
+
2.6.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 David Runger
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
[](https://codecov.io/gh/davidrunger/living_document)
|
2
|
+
|
3
|
+
# LivingDocument
|
4
|
+
|
5
|
+
LivingDocument evaluates Ruby statements inline in your code editor, which can be particularly useful when writing examples of Ruby code for documentation purposes.
|
6
|
+
|
7
|
+
For example, if you write this in your editor...
|
8
|
+
|
9
|
+
```rb
|
10
|
+
(1..10).select(&:even?)
|
11
|
+
###
|
12
|
+
```
|
13
|
+
|
14
|
+
... then, when you save the file, it will be updated by LivingDocument to this...
|
15
|
+
|
16
|
+
```rb
|
17
|
+
(1..10).select(&:even?)
|
18
|
+
# => [2, 4, 6, 8, 10]
|
19
|
+
```
|
20
|
+
|
21
|
+
Additionally, any subsequent edits, when saved, will also be reflected. For example, if you change `even?` to `odd?` in the above example (and save the file), then LivingDocument will update the output shown in the `# =>` line, producing:
|
22
|
+
|
23
|
+
```rb
|
24
|
+
(1..10).select(&:odd?)
|
25
|
+
# => [1, 3, 5, 7, 9]
|
26
|
+
```
|
27
|
+
|
28
|
+
In other words, the special markers `###` and `# =>` tell LivingDocument to evaluate the line of code immediately above and insert the evaluated result at the position of the marker whenever the file is saved.
|
29
|
+
|
30
|
+
## Table of Contents
|
31
|
+
|
32
|
+
<!--ts-->
|
33
|
+
* [LivingDocument](#livingdocument)
|
34
|
+
* [Table of Contents](#table-of-contents)
|
35
|
+
* [Installation](#installation)
|
36
|
+
* [Usage](#usage)
|
37
|
+
* [Markdown support](#markdown-support)
|
38
|
+
* [Time is frozen](#time-is-frozen)
|
39
|
+
* [Development](#development)
|
40
|
+
* [For maintainers](#for-maintainers)
|
41
|
+
* [License](#license)
|
42
|
+
|
43
|
+
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
|
44
|
+
<!-- Added by: david, at: Wed Jan 29 07:45:21 PM CST 2025 -->
|
45
|
+
|
46
|
+
<!--te-->
|
47
|
+
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
```
|
51
|
+
$ gem install living_document
|
52
|
+
```
|
53
|
+
|
54
|
+
Or, if you would like to add it to a `Gemfile`:
|
55
|
+
|
56
|
+
```rb
|
57
|
+
gem 'living_document'
|
58
|
+
```
|
59
|
+
|
60
|
+
## Usage
|
61
|
+
|
62
|
+
Put the following content into a file. For this example, we'll call it `ruby.rb`, but you can use any file path that you like.
|
63
|
+
|
64
|
+
```rb
|
65
|
+
1 + 2
|
66
|
+
###
|
67
|
+
|
68
|
+
5 / 0
|
69
|
+
###
|
70
|
+
|
71
|
+
puts('This is one great string!')
|
72
|
+
###
|
73
|
+
```
|
74
|
+
|
75
|
+
Then run `livdoc <path-to-your-file>` on your command line. In this example, that is:
|
76
|
+
|
77
|
+
```
|
78
|
+
$ livdoc ruby.rb
|
79
|
+
```
|
80
|
+
|
81
|
+
Then, go back to the file in your editor and save it. The file's content should be transformed to this:
|
82
|
+
|
83
|
+
```rb
|
84
|
+
1 + 2
|
85
|
+
# => 3
|
86
|
+
|
87
|
+
5 / 0
|
88
|
+
# => raises ZeroDivisionError
|
89
|
+
|
90
|
+
puts('This is one great string!')
|
91
|
+
# => prints "This is one great string!"
|
92
|
+
```
|
93
|
+
|
94
|
+
Then, edit the file and save it again. You'll see that the `# => ` comments are automatically and immediately updated to reflect your edits.
|
95
|
+
|
96
|
+
## Markdown support
|
97
|
+
|
98
|
+
LivingDocument can also handle Markdown code, which is especially convenient when developing
|
99
|
+
documentation with examples.
|
100
|
+
|
101
|
+
To use this functionality, simply provide a markdown document as the target file for `livdoc`, e.g.:
|
102
|
+
|
103
|
+
```
|
104
|
+
$ livdoc README.md
|
105
|
+
```
|
106
|
+
|
107
|
+
**NOTE:** Only code blocks that begin with `` ```rb `` or `` ```ruby `` will be evaluated.
|
108
|
+
|
109
|
+
For example, LivingDocument will turn this...
|
110
|
+
|
111
|
+
~~~markdown
|
112
|
+
This is how you do addition in Ruby:
|
113
|
+
|
114
|
+
```rb
|
115
|
+
2 + 3
|
116
|
+
###
|
117
|
+
```
|
118
|
+
|
119
|
+
This is how you do exponentiation in Ruby:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
2**4
|
123
|
+
###
|
124
|
+
```
|
125
|
+
~~~
|
126
|
+
|
127
|
+
...into this...
|
128
|
+
|
129
|
+
~~~markdown
|
130
|
+
This is how you do addition in Ruby:
|
131
|
+
|
132
|
+
```rb
|
133
|
+
2 + 3
|
134
|
+
# => 5
|
135
|
+
```
|
136
|
+
|
137
|
+
This is how you do exponentiation in Ruby:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
2**4
|
141
|
+
# => 16
|
142
|
+
```
|
143
|
+
~~~
|
144
|
+
|
145
|
+
## Time is frozen
|
146
|
+
|
147
|
+
NOTE: Time is frozen (using [`timecop`](https://github.com/travisjeffery/timecop)) when your code is executed. This could cause unexpected results if your code depends the `Time` being different when different lines of code execute.
|
148
|
+
|
149
|
+
To illustrate, note that `time_1` and `time_2` below are the same (which they wouldn't be, if run in a normal Ruby program).
|
150
|
+
|
151
|
+
```rb
|
152
|
+
time_1 = Time.now.iso8601(6)
|
153
|
+
# => "2025-01-29T18:54:23.134962-06:00"
|
154
|
+
|
155
|
+
time_2 = Time.now.iso8601(6)
|
156
|
+
# => "2025-01-29T18:54:23.134962-06:00"
|
157
|
+
|
158
|
+
time_2 > time_1
|
159
|
+
# => false
|
160
|
+
```
|
161
|
+
|
162
|
+
## Development
|
163
|
+
|
164
|
+
To install this gem onto your local machine from a development copy of the code, run `bundle exec
|
165
|
+
rake install`.
|
166
|
+
|
167
|
+
## For maintainers
|
168
|
+
|
169
|
+
To release a new version, run `bin/release` with an appropriate `--type` option, e.g.:
|
170
|
+
|
171
|
+
```
|
172
|
+
bin/release --type minor
|
173
|
+
```
|
174
|
+
|
175
|
+
(This uses the [`runger_release_assistant`](https://github.com/davidrunger/runger_release_assistant) gem.)
|
176
|
+
|
177
|
+
## License
|
178
|
+
|
179
|
+
The gem is available as open source under the terms of the [MIT
|
180
|
+
License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/_guard-core
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application '_guard-core' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
bundle_binstub = File.expand_path('bundle', __dir__)
|
15
|
+
|
16
|
+
if File.file?(bundle_binstub)
|
17
|
+
if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
|
18
|
+
load(bundle_binstub)
|
19
|
+
else
|
20
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
21
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
require 'bundler/setup'
|
27
|
+
|
28
|
+
load Gem.bin_path('guard', '_guard-core')
|
data/bin/console
ADDED
data/bin/guard
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'guard' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
bundle_binstub = File.expand_path('bundle', __dir__)
|
15
|
+
|
16
|
+
if File.file?(bundle_binstub)
|
17
|
+
if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
|
18
|
+
load(bundle_binstub)
|
19
|
+
else
|
20
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
21
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
require 'bundler/setup'
|
27
|
+
|
28
|
+
load Gem.bin_path('guard', 'guard')
|
data/bin/release
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'release' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
bundle_binstub = File.expand_path('bundle', __dir__)
|
15
|
+
|
16
|
+
if File.file?(bundle_binstub)
|
17
|
+
if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
|
18
|
+
load(bundle_binstub)
|
19
|
+
else
|
20
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
21
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
require 'bundler/setup'
|
27
|
+
|
28
|
+
load Gem.bin_path('release_assistant', 'release')
|
data/bin/rspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
bundle_binstub = File.expand_path('bundle', __dir__)
|
15
|
+
|
16
|
+
if File.file?(bundle_binstub)
|
17
|
+
if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
|
18
|
+
load(bundle_binstub)
|
19
|
+
else
|
20
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
21
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
require 'bundler/setup'
|
27
|
+
|
28
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
data/bin/rubocop
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
bundle_binstub = File.expand_path('bundle', __dir__)
|
15
|
+
|
16
|
+
if File.file?(bundle_binstub)
|
17
|
+
if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
|
18
|
+
load(bundle_binstub)
|
19
|
+
else
|
20
|
+
abort(<<~ERROR)
|
21
|
+
Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.
|
23
|
+
ERROR
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'rubygems'
|
28
|
+
require 'bundler/setup'
|
29
|
+
|
30
|
+
load Gem.bin_path('rubocop', 'rubocop')
|
data/exe/livdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'listen'
|
6
|
+
|
7
|
+
require_relative '../lib/living_document.rb'
|
8
|
+
|
9
|
+
# rubocop:disable Style/TopLevelMethodDefinition
|
10
|
+
def evaluate_code_and_update_source_file(file_path)
|
11
|
+
puts('Running code...')
|
12
|
+
code_in_file = File.read(file_path)
|
13
|
+
code_to_write =
|
14
|
+
LivingDocument::DocumentEvaluator.new(
|
15
|
+
document: code_in_file,
|
16
|
+
).evaluated_document
|
17
|
+
|
18
|
+
$printed_objects_last_run = []
|
19
|
+
puts("Writing file! #{Time.now}")
|
20
|
+
File.write(file_path, code_to_write)
|
21
|
+
end
|
22
|
+
# rubocop:enable Style/TopLevelMethodDefinition
|
23
|
+
|
24
|
+
file_path = ARGV[0]
|
25
|
+
|
26
|
+
if file_path.nil?
|
27
|
+
puts('You must provide a file path argument, e.g. `livdoc personal/ruby.rb`.')
|
28
|
+
exit(1)
|
29
|
+
end
|
30
|
+
|
31
|
+
last_file_update = Time.now
|
32
|
+
listener =
|
33
|
+
Listen.to(Dir.pwd, only: /\A#{Regexp.escape(file_path)}\z/) do |_modified, _added, _removed|
|
34
|
+
# Don't enter infinitely recursive loop, since the code below triggers file updates.
|
35
|
+
# After file has been updated, wait at least 0.5 seconds before listener processes again.
|
36
|
+
next if (Time.now - last_file_update) < 0.5
|
37
|
+
|
38
|
+
evaluate_code_and_update_source_file(file_path)
|
39
|
+
|
40
|
+
last_file_update = Time.now
|
41
|
+
end
|
42
|
+
|
43
|
+
listener.start
|
44
|
+
system('clear')
|
45
|
+
evaluate_code_and_update_source_file(file_path)
|
46
|
+
puts('Waiting for file changes...')
|
47
|
+
|
48
|
+
at_exit do
|
49
|
+
print('Stopping listener ... ')
|
50
|
+
listener.stop
|
51
|
+
puts('done.')
|
52
|
+
end
|
53
|
+
|
54
|
+
sleep
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class LivingDocument::CodeEvaluator
|
4
|
+
prepend MemoWise
|
5
|
+
|
6
|
+
def initialize(code:)
|
7
|
+
@code = code.gsub(/^=begin\b.*?^=end\n/m, '')
|
8
|
+
|
9
|
+
@known_erroring_segment_indexes = []
|
10
|
+
@random_seed = rand(1_000_000_000)
|
11
|
+
|
12
|
+
$printed_output_last_run = ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def evaluated_code
|
16
|
+
Timecop.freeze do
|
17
|
+
printed_code_segments.each_with_index do |printed_code_segment, index|
|
18
|
+
$printed_output = ''
|
19
|
+
set_up_capturing_stdout
|
20
|
+
|
21
|
+
result =
|
22
|
+
begin
|
23
|
+
# we need to namespace any constants that would otherwise leak and persist globally
|
24
|
+
new_namespace.instance_eval(code_to_eval(index)).inspect.squish
|
25
|
+
rescue => error
|
26
|
+
# Comment these lines back in for debugging:
|
27
|
+
# puts("ERROR: #{error.class}:#{error.message}")
|
28
|
+
# puts(error.backtrace)
|
29
|
+
@known_erroring_segment_indexes << index
|
30
|
+
"raises #{error.class} (#{error.message})"
|
31
|
+
end
|
32
|
+
|
33
|
+
if newly_printed_output.present?
|
34
|
+
result = result_for_printed_output
|
35
|
+
elsif result.include?('\"')
|
36
|
+
result = "'#{result.gsub('\"', '"')[1...-1]}'"
|
37
|
+
end
|
38
|
+
remember_printed_objects
|
39
|
+
|
40
|
+
swap_in_evaluated_code(printed_code_segment, result)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
restore_original_stdout
|
45
|
+
|
46
|
+
@code
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def result_for_printed_output
|
52
|
+
if newly_printed_output[0..-2].include?("\n")
|
53
|
+
%(prints:\n#{commented_output(newly_printed_output)})
|
54
|
+
else
|
55
|
+
%(prints "#{newly_printed_output.rstrip}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def commented_output(printed_output)
|
60
|
+
<<~COMMENTED_OUTPUT.rstrip
|
61
|
+
=begin
|
62
|
+
#{printed_output.delete_suffix("\n")}
|
63
|
+
=end
|
64
|
+
COMMENTED_OUTPUT
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_up_capturing_stdout
|
68
|
+
@original_stdout = $stdout
|
69
|
+
$stdout = StringIO.new
|
70
|
+
end
|
71
|
+
|
72
|
+
def restore_original_stdout
|
73
|
+
$stdout = @original_stdout
|
74
|
+
end
|
75
|
+
|
76
|
+
def code_segments_to_eval(current_index)
|
77
|
+
printed_code_segments_to_eval(current_index)
|
78
|
+
end
|
79
|
+
|
80
|
+
def code_to_eval(current_index)
|
81
|
+
code_segments_to_eval(current_index).join('')
|
82
|
+
end
|
83
|
+
|
84
|
+
def indexes_to_eval(current_index)
|
85
|
+
(0..current_index).to_a.reject { @known_erroring_segment_indexes.include?(_1) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def new_namespace
|
89
|
+
random_seed = @random_seed
|
90
|
+
Module.new.tap do |new_module|
|
91
|
+
new_module.instance_eval do
|
92
|
+
srand(random_seed)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def newly_printed_output
|
98
|
+
$printed_output = $stdout.string.dup
|
99
|
+
$printed_output.delete_prefix($printed_output_last_run)
|
100
|
+
end
|
101
|
+
|
102
|
+
memo_wise \
|
103
|
+
def printed_code_segments
|
104
|
+
@code.scan(/(?:(?!###|# =>).)*(?:###|# =>)[^\n]*\s*/mi)
|
105
|
+
end
|
106
|
+
|
107
|
+
def printed_code_segments_to_eval(current_index)
|
108
|
+
printed_code_segments.values_at(*indexes_to_eval(current_index))
|
109
|
+
end
|
110
|
+
|
111
|
+
def remember_printed_objects
|
112
|
+
$printed_output_last_run = $printed_output
|
113
|
+
end
|
114
|
+
|
115
|
+
def swap_in_evaluated_code(printed_code_segment, result)
|
116
|
+
@code[printed_code_segment] = printed_code_segment.sub(/(?:# =>|###)[^\n]*$/, "# => #{result}")
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class LivingDocument::DocumentEvaluator
|
4
|
+
def initialize(document:)
|
5
|
+
@document = document.dup
|
6
|
+
end
|
7
|
+
|
8
|
+
def evaluated_document
|
9
|
+
if markdown?
|
10
|
+
markdown_codeblocks.each do |markdown_codeblock|
|
11
|
+
opening, *ruby_code_lines, closing = markdown_codeblock.split("\n")
|
12
|
+
ruby_code = ruby_code_lines.join("\n")
|
13
|
+
evaluated_ruby_code =
|
14
|
+
LivingDocument::CodeEvaluator.new(
|
15
|
+
code: ruby_code,
|
16
|
+
).evaluated_code
|
17
|
+
@document[markdown_codeblock] =
|
18
|
+
<<~EVALUATED_CODEBLOCK.rstrip
|
19
|
+
#{opening}
|
20
|
+
#{evaluated_ruby_code}
|
21
|
+
#{closing}
|
22
|
+
EVALUATED_CODEBLOCK
|
23
|
+
end
|
24
|
+
@document
|
25
|
+
else
|
26
|
+
LivingDocument::CodeEvaluator.new(
|
27
|
+
code: @document,
|
28
|
+
).evaluated_code
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def markdown?
|
33
|
+
!markdown_codeblocks.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def markdown_codeblocks
|
39
|
+
@document.scan(/```(?:ruby|rb)\n(?:(?!```\n).)*```/mi)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/living_document/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'living_document'
|
7
|
+
spec.version = LivingDocument::VERSION
|
8
|
+
spec.authors = ['David Runger']
|
9
|
+
spec.email = ['davidjrunger@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = 'Evaluate Ruby code live while editing a file!'
|
12
|
+
spec.description = 'Evaluate Ruby code live while editing a file!'
|
13
|
+
spec.homepage = 'https://github.com/davidrunger/living_document'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
required_ruby_version = File.read('.ruby-version').rstrip.sub(/\A(\d+\.\d+)\.\d+\z/, '\1.0')
|
17
|
+
spec.required_ruby_version = ">= #{required_ruby_version}"
|
18
|
+
|
19
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
20
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
+
spec.metadata['source_code_uri'] = 'https://github.com/davidrunger/living_document'
|
22
|
+
spec.metadata['changelog_uri'] = 'https://github.com/davidrunger/living_document/blob/main/CHANGELOG.md'
|
23
|
+
|
24
|
+
# Specify which files should be added to the gem when it is released.
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
26
|
+
spec.files =
|
27
|
+
Dir.chdir(File.expand_path(__dir__)) do
|
28
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
29
|
+
end
|
30
|
+
spec.bindir = 'exe'
|
31
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
|
+
|
33
|
+
spec.add_dependency('activesupport', '>= 6')
|
34
|
+
spec.add_dependency('listen', '>= 3.2')
|
35
|
+
spec.add_dependency('memo_wise', '>= 1.7')
|
36
|
+
spec.add_dependency('timecop', '>= 0.9.10')
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: living_document
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Runger
|
8
|
+
bindir: exe
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-01-30 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: activesupport
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '6'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '6'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: listen
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.2'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.2'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: memo_wise
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.7'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.7'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: timecop
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.9.10
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.9.10
|
68
|
+
description: Evaluate Ruby code live while editing a file!
|
69
|
+
email:
|
70
|
+
- davidjrunger@gmail.com
|
71
|
+
executables:
|
72
|
+
- livdoc
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".github/dependabot.yml"
|
77
|
+
- ".github/workflows/ruby.yml"
|
78
|
+
- ".gitignore"
|
79
|
+
- ".release_assistant.yml"
|
80
|
+
- ".rubocop.yml"
|
81
|
+
- ".ruby-version"
|
82
|
+
- ".runger-config.yml"
|
83
|
+
- CHANGELOG.md
|
84
|
+
- Gemfile
|
85
|
+
- Gemfile.lock
|
86
|
+
- LICENSE.txt
|
87
|
+
- README.md
|
88
|
+
- Rakefile
|
89
|
+
- bin/_guard-core
|
90
|
+
- bin/console
|
91
|
+
- bin/githooks/pre-push
|
92
|
+
- bin/guard
|
93
|
+
- bin/release
|
94
|
+
- bin/rspec
|
95
|
+
- bin/rubocop
|
96
|
+
- exe/livdoc
|
97
|
+
- lib/living_document.rb
|
98
|
+
- lib/living_document/code_evaluator.rb
|
99
|
+
- lib/living_document/document_evaluator.rb
|
100
|
+
- lib/living_document/version.rb
|
101
|
+
- living_document.gemspec
|
102
|
+
homepage: https://github.com/davidrunger/living_document
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
metadata:
|
106
|
+
rubygems_mfa_required: 'true'
|
107
|
+
homepage_uri: https://github.com/davidrunger/living_document
|
108
|
+
source_code_uri: https://github.com/davidrunger/living_document
|
109
|
+
changelog_uri: https://github.com/davidrunger/living_document/blob/main/CHANGELOG.md
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 3.4.0
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubygems_version: 3.6.2
|
125
|
+
specification_version: 4
|
126
|
+
summary: Evaluate Ruby code live while editing a file!
|
127
|
+
test_files: []
|