-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.org
289 lines (208 loc) · 10.2 KB
/
README.org
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#+PROPERTY: header-args :eval yes
#+title: OrgWeb: CLI Org-Mode Environment for WEB like development without Emacs
=orgweb= is intended for developers that want to create literate programming
project using Org-mode, but that *does not* want to invest time to learn how to
use Emacs and Org-mode. If you are a developer that already uses Emacs and
Org-mode, this tool is most likely not for you, but maybe for the people on your
team that doesn't know, nor want to know, Emacs.
=orgweb= is a very simple CLI tool that does the following:
1. =tangle= one or multiple Org files
2. =detangle= one or multiple source files
3. =execute= one or multiple Org files
4. =monitor= file changes on the file system to automatically =tangle= and
=detangle= files that changes.
[[https://fgiasson.com/blog/index.php/2023/08/28/what-is-literate-programming-why/][What is Literate Programming? Why?]]
If you wonder what a Literate Programming project looks like, just poke around
this repository to have a glimpse of the potential.
* How does it work?
=orgweb= is designed in a way that developers can use all the power of Org-mode,
in any IDE they like, without having to rely on Emacs directly.
To do that, it leverages Docker to build an image where Emacs is properly
installed and configured to implement the commands that are exposed via the
command line tool.
If the =orgweb= docker image is not currently existing in the environment, then
it will request Docker to build the image using the Dockerfile. The build
process will install and configure all the components required to implement all
=orgweb= commands.
=orgweb= check if it exists every time it is invoked from the command line. This
process will happen any time that the image is not available in the environment.
#+BEGIN_SRC plantuml :file imgs/orgweb.svg :exports results
OrgWeb -> Docker: Command
Docker -> Image: Build Image
Image -> Emacs: Install & Configure
#+END_SRC
#+RESULTS:
[[file:imgs/orgweb.svg]]
If the image is existing in the environment, then the following will happen.
=orgweb= will ask Docker to create a container based on the image. Once the
container is running, it will execute a command on the container's terminal to
run Emacs. Emacs is used directly from the command line by evaluating ELisp code
it gets as input.
Every time a =orgweb= command line is executed, a new container is created:
#+BEGIN_SRC plantuml :file imgs/orgweb_2.svg :exports results
OrgWeb -> Docker: Run Container
Docker -> Container: Create Container
Image <-- Container: Uses
OrgWeb -> Emacs: Execute Command
Docker -> Container: Deletes
#+END_SRC
#+RESULTS:
[[file:imgs/orgweb_2.svg]]
* Installing
** Docker
If Docker is already installed in your development environment, you can skip
this step. Otherwise, you should install Docker.
[[https://docs.docker.com/desktop/][To install Docker Desktop, you simply have read and follow those instructions.]]
** From Package
=orgweb= is available on PyPi, you can easily install it locally by running the
following command in your terminal:
#+begin_src shell :eval no
pip install orgweb
#+end_src
** From Source
If you want to improve and contribute to the project, you will first have to
generate the sources files from the Org mode files in the repository. To do so,
you will need =orgweb= itself (installed in the previous step), or you could do
the same if you have a local Emacs instance configured with =org-mode=. But
let's assumes you don't.
First clone the repository in your environment:
#+begin_src shell :eval no
git clone https://github.com/fgiasson/orgweb.git
#+end_src
Once the repository is cloned, let's tangle all the files:
#+begin_src shell :eval no
cd orgweb
orgweb tangle .
#+end_src
These commands will tangle all the sources and configuration files required by
the project.
Once they have been tangle, you will be able to use make to create the
development environment and the package to run locally.
#+begin_src shell :eval no
make create-venv # create the pyenv virtual environment
source .venv/bin/activate # source that environment
make install-build # install Python's build
make build # build the orgweb CLI application
make install-local-build # install the package we just created
#+end_src
After that, you will be able to run =make rebuid-local= every time you want to
test some changes you made to the application.
* Usage
** Folder Structure
Each of the operation work with the same folder structure assumption. There are three main components:
1. folder
2. files
The =folder= is a where the =files= are located, within the =project folder=.
The =files= is a list of one or multiple files we want to tangle.
** Tangle
=orgweb tangle= takes a =folder= as input. The =folder= is where the Org files
we want to tangle are located. The operation is recursive, it will check in all
subfolders of =folder=
Optionally, one or multiple files can be listed. Those files are located in
=folder=, and those are the ones that will be tangled from that folder.
If no file is mentioned, then all the Org files from =folder= will be tangled.
#+begin_src shell :eval no
cd /my/project/folder/
orgweb tangle . --file=foo.org --file=bar.org
#+end_src
In that example, =orgweb= will tangle the two files =/my/project/folder/foo.org=
and =/my/project/folder/bar.org=
** Detangle
=orgweb detangle= takes a =folder= as input. The =folder= is where the source
files we want to detangle are located. The operation is recursive, it will check in all
subfolders of =folder=
Optionally, one or multiple files can be listed. Those files are located in
=folder=, and those are the ones that will be detangled from that folder.
If no file is mentioned, then all the Org files from =folder= will be detangled.
The =detangle= command does make sure that an input source file is a file that
was previously tangled. Otherwise, it will be ignored. It does so by checking
the tangling markup in comments of the source file.
#+begin_src shell :eval no
cd /my/project/folder/
orgweb detangle . --file=foo.py --file=bar.py
#+end_src
In that example, =orgweb= will detangle the two files
=/my/project/folder/foo.py= and =/my/project/folder/bar.py=
** Execute
=orgweb execute= takes a =folder= as input. The =folder= is where the Org files
we want to execute are located. The operation is recursive, it will check in all
subfolders of =folder=
Optionally, one or multiple files can be listed. Those files are located in
=folder=, and those are the ones that will be executed from that folder.
If no file is mentioned, then all the Org files from =folder= will be executed.
The =execute= command is used to execute every code block or the Org files. This
is normally used to execute PlantUML code blocks such that it produces graphs
that are referrenced within Org files.
#+begin_src shell :eval no
cd /my/project/folder/
orgweb execute . --file=foo.org
#+end_src
In that example, =orgweb= will execute the =/my/project/folder/foo.py=
** Monitor
=orgweb monitor= will take a folder as input and will monitor every file changes
in that directory, recursively. If a Org file changes, it will be tangled, if a
source file changes it will be detangled.
Monitoring is used to make sure that the Org files and their source files are
always in sync, without having the developers to carefully tangle and detangle
every time they modify a file.
#+begin_src shell :eval no
cd /my/project/folder/
orgweb monitor .
#+end_src
* Tangling Workflows
Let's take some time to cover the different tangling workflows that you may
imagine.
The first scenario is when you have a single Org file that tangles code blocks
in one, or multiple, source files, such as:
#+BEGIN_SRC plantuml :file imgs/graph.svg :exports results
digraph foo {
"Foo.org" [color=green];
"Foo.py" [color=blue];
"Bar.py" [color=blue];
"Foo.org" -> "Foo.py" [label="tangle", color=blue, fontcolor=blue];
"Foo.org" -> "Bar.py" [label="tangle", color=blue, fontcolor=blue];
"Foo.py" -> "Foo.org" [label="detangle", color=green, fontcolor=green];
"Bar.py" -> "Foo.org" [label="detangle", color=green, fontcolor=green];
}
#+END_SRC
#+RESULTS:
[[file:imgs/graph.svg]]
This is the workflow that is currently implemented in Org-mode. You can tangle a
=foo.org= file in as many source files you want. Then, if you just detangle
=Foo.py=, then only the code blocks with that code will be updated in =Foo.org=.
Then you could extrapolate this case and think about the following scenario:
#+BEGIN_SRC plantuml :file imgs/graph_2.svg :exports results
digraph foo {
layout=circo;
"Foo.org" [color=green];
"Bar.org" [color=blue];
"FooBar.py" [color=orange];
"Foo.org" -> "FooBar.py" [label="tangle", color=orange, fontcolor=orange];
"Bar.org" -> "FooBar.py" [label="tangle", color=orange, fontcolor=orange];
"FooBar.py" -> "Foo.org" [label="detangle", color=green, fontcolor=green];
"FooBar.py" -> "Bar.org" [label="detangle", color=blue, fontcolor=blue];
}
#+END_SRC
#+RESULTS:
[[file:imgs/graph_2.svg]]
This scenario is when you have two different Org files that tangle in the same
source file. Then, when you detangle =FooBar.py=, you would imagine that each
blocks would detangle in their respective Org file.
However, this is not currently the case with Org mode. *This scenario is
currently not supported and will break your literate programming workkflow*.
Another thing to take care of is that the [[https://orgmode.org/manual/Noweb-Reference-Syntax.html][noweb syntax is not currently
supported for the detangle command]]. This is a long standing issue with
Org-mode that is discussed for several years now.
You can use =noweb= only if you won't =detangle= your source files.
* Contributions
We welcome contributions to OrgWeb! If you’d like to contribute, please follow
these steps:
1. Fork the repository on GitHub.
2. Create a new branch with a descriptive name: =git checkout -b
feature/your-feature-name=
3. Push your changes to your fork: =git push origin feature/your-feature-name=
4. Make your changes and commit them: =git commit -m "Add feature: your
feature name"=
5. Submit a pull request to the main branch of the original repository.
6. Make sure that you only commit the Org-mode files, and not the source files
themselves. Add them to the =make clean= method if needed.