vfl 0.0.0.1

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.
data/documentation.pdf ADDED
Binary file
data/documentation.tex ADDED
@@ -0,0 +1,366 @@
1
+ \documentclass{article}
2
+ \setlength{\parindent}{0cm}
3
+
4
+ @(vfl) = **Vanilla Flavored LaTex**
5
+
6
+ @(github_url) = http://github.com/adhithyan15/vanilla
7
+
8
+ @(tmaker) = **TexMaker**
9
+
10
+ @(ftb) = formatted text blocks
11
+
12
+ @(test) = 15
13
+
14
+ @(testy) = 27
15
+
16
+ @(test1) = 17 + @(test) + @(testy)
17
+
18
+ #(cftb)[] = [$(cap)[formatted text blocks]]
19
+
20
+ $(importpack)[documentation]
21
+
22
+ \begin{document}
23
+
24
+ \begin{center}
25
+
26
+ \huge{Vanilla Documentation}\vspace{5pt}
27
+
28
+ \large{**Everything that you need to know about Vanilla**}
29
+
30
+ \end{center}
31
+
32
+ \vspace{30pt}
33
+
34
+ \section*{Copyright}
35
+
36
+ **\textcopyright Adhithya Rajasekaran, Renuka Rajasekaran, Sri Madhavi Rajasekaran**. All the contents in this document are released under a *[creative commons license => http://creativecommons.org/licenses/by-nd/3.0/].
37
+
38
+ \section*{What is Vanilla?}
39
+
40
+ Vanilla is a powerful LaTex preprocessor. It works based on the DRY(Don't Repeat Yourself) principle. It aims to reduce the entry barrier and the learning curve for Latex by simplifying the syntax and also reducing the verbosity of Latex. In this documentation you will learn how to write @(vfl) documents. This document itself is written in @(vfl) \vspace{5pt}
41
+
42
+ \section*{Why Vanilla?}
43
+
44
+ LaTex is a wonderful typesetting system but its reach is limited because of its complexity, verbose syntax and steep learning curve. So @(vfl) is directed towards solving those above mentioned problems. It derives most of its ideas from
45
+ **Markdown**, a small but powerful markup language.
46
+
47
+ \section*{Open Source Project}
48
+
49
+ The authors of this project have decided to open source the source code of the project. The code is hosted on *[github => https://github.com/adhithyan15/vanilla]. The code is released under MIT License. Please report any bugs to the *[issues => https://github.com/adhithyan15/vanilla/issues?state=open] tab on our github homepage. If you have any new ideas or suggestions, please leave them on the issues tab. We will greatly appreciate your feedback.
50
+
51
+ \section*{Technical Details}
52
+
53
+ Vanilla first started out as a separate markup language with a backward compatiblity to Latex. But it became apparent that there will be not enough interest in creating large amounts of libraries and productivity tools for Vanilla alone. So the authors departed from the idea and made it a preprocessor that incorporated a lot of features from their original markup language idea. \vspace{5pt}
54
+
55
+ Any LaTex document is a valid @(vfl) document but no @(vfl) document is a valid LaTex document without being processed through the Vanilla. \vspace{5pt}
56
+
57
+ The original compiler prototype was built using Matlab and then Python for more reachability. The preprocessor grew out of that compiler and was rewritten from scratch in Ruby and is shipped as a commandline utility.\vspace{5pt}
58
+
59
+ Vanilla builds on top of **PDFLatex**. So it is very important that you have any of the major tex distributions installed on your computer. If you are on windows we recommend *[MikTex => www.miktex.org] and on mac, we recommend *[MacTex => http://tug.org/mactex/]. \vspace{5pt}
60
+
61
+ \section*{Current State}
62
+
63
+ The current and stable vanilla release is version 1.0. The release provides a minimal set of base features which might be retained in most of the future releases. Significant amounts of features have been left out either due to bugs or incomplete implementation or not enough testing. They will be released in the upcoming releases. One of the main drawbacks of Vanilla is that it doesn't ship with an **error catcher and notifier**. So Vanilla will simply ignore the errors and try to compile the error free parts of the document.\vspace{5pt}
64
+
65
+ \section*{Getting Vanilla}
66
+
67
+ It is very easy to get Vanilla. Visit www.adhithyan15.github.com/vanilla/ and follow the steps below.
68
+
69
+ \begin{enumerate}
70
+
71
+ \item Click on "Download Zip" to download both the source of the compiler and also the compiled version of the compiler. \vspace{5pt}
72
+
73
+ \includegraphics[scale = 0.35]{VanillaGithub}
74
+
75
+ \item Extract the downloaded zip file using Winzip or any other archive extractor. If you don't have an archive extractor, we recommend *[ 7-zip => www.7zip.org ]
76
+
77
+ \item Once you extract it, you will find the following files inside the folder you extracted
78
+
79
+ \begin{itemize}
80
+
81
+ \item **bin**: The bin directory contains **Vanilla.exe**,**Vanilla**,and **Vanilla.rb** files. **Vanilla.exe** is the primary compiler for the windows platform and **Vanilla** is the primary compiler for the unix platform. **Vanilla.rb** file contains the ruby source code of the compiler.
82
+ \item **Old Compiler Prototypes**: This directory contains the prototype compilers written in Python and Matlab. Those have been open sourced just for reference purposes.
83
+ \item **Readme.md**: Since the project is hosted in *[ Github => @(github_url) ], Github added a readme file markuped in **Markdown**.
84
+ \item **VanillaGithub.jpg**: A screenshot of http://adhithyan15.github.com/vanilla page.
85
+ \item **Documentation.pdf**: This is the same document that you are reading right now.
86
+ \item **Documentation.tex**: This is the .tex version of documentation written using @(vfl). I highly recommend you to read through this document so that you can get example usages of @(vfl).
87
+ \item **Documentation.log**: Log file produced by **LaTex** when the file is being compiled to PDF.
88
+
89
+ \end{itemize}
90
+
91
+ \item For windows users, please follow *[this => https://github.com/adhithyan15/vanilla/wiki/Adding-Vanilla-to-Path] tutorial to add the Vanilla.exe to your path so that it can be accessed from your commandline prompt. Mac and other Unix based OS please follow *[this => https://github.com/adhithyan15/vanilla/wiki/Getting-Started-With-Vanilla-Mac-and-Unix] tutorial to add the utility to your terminal/bash.
92
+
93
+ \item You are all set. You can compile your @(vfl) documents by calling **"vanilla -~-compile somefile.tex"**. You have to set the directory in which your @(vfl) document is located as your **current directory** for the above command to work.
94
+
95
+ Please see *[this => https://github.com/adhithyan15/vanilla/wiki/Compiling-Vanilla-Flavored-LaTex-Documents] tutorial to understand what the above phrase is describing.
96
+
97
+ \end{enumerate}
98
+
99
+ Vanilla compiler can work with LaTex Editors. But configuration seems to be a problem. Vanilla is an unconventional preprocessor in which it doesn't have a seperate extension. After the preprocessing stage, Vanilla needs the authority to overwrite the original file and many of the LaTex editors block that kind of action from happening. So a solution is under development. Until such time, you can use Notepad, Notepad++, Wordpad or Sublime Text.
100
+
101
+ \section*{Features of Vanilla}
102
+
103
+ @(vfl) offers a lot of features to enhance people's productivity with LaTex. Let us see what those features below
104
+
105
+ \begin{itemize}
106
+
107
+ \item **Multiline Comments**: In @(vfl) you can comment out multiple lines of code using matlab style comments. Let us see a quick demo of this feature
108
+
109
+ ###
110
+
111
+ %You can comment out multiple lines using %{.....}%
112
+
113
+ %{Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris placerat tristique purus,
114
+ non tempus mi ultrices in. Praesent lobortis erat et lorem commodo mollis. Pellentesque
115
+ eu euismod nulla.Ut vitae consequat est. Quisque adipiscing rhoncus tellus, eu fermentum
116
+ augue tincidunt ut. Proin a dui dignissim massa auctor iaculis dictum a purus. Suspendisse
117
+ porta felis at velit placerat varius.}%
118
+
119
+ ###
120
+
121
+ Vanilla compiler converts @(vfl) multiline comments into several single line LaTex comments. Vanilla compiler doesn't touch the LaTex comments. So they are still valid.
122
+
123
+ \item **Constants**: Constants are very similar to variables but they are immutable. In @(vfl), you can declare constants
124
+ through the following sytax $@(constant\_name) = value$. Note: LaTex has offers mutable variables. We are working on implementing mutable variables in Vanilla. It will be released in
125
+ version 2.0.
126
+
127
+ ###
128
+
129
+ @(vfl) = **Vanilla Flavored LaTex** %must be declared in the preamble
130
+
131
+ %Usage
132
+
133
+ Welcome to @(vfl) %should output Welcome to \textbf{Vanilla Flavored LaTex}
134
+
135
+ ###
136
+
137
+ Constants now support what is known as a **Computed Property**. You can build new constants from other constants. An example is provided below
138
+
139
+ ###
140
+
141
+ @(test) = 15
142
+
143
+ @(testy) = 27
144
+
145
+ @(test1) = 17 + @(test) + @(testy)
146
+
147
+ ###
148
+
149
+ That should output @(test1). **Computed Properties** features currently doesn't support string concatenation. But it will be improved as time goes on. This addition resolves *[issue 15 => https://github.com/adhithyan15/vanilla/issues/15] on project page. Vanilla compiler doesn't compile the Vanilla constants into LaTex variables. Instead, it converts them into plain text so that they can be used in a variety of purposes.
150
+ Since the constants are rendered into plain text all the you can pass in a variable to most of the features listed below.
151
+ \item **Formatted Text Blocks**: #(cftb)[] were inspired by Less CSS' parametric mixins. #(cftb)[] can include any kind of LaTex or @(vfl) formatting.
152
+ @(vfl) forces the @(ftb) to be declared inside preamble to increase readability and @(ftb) are immutable. Mutable @(ftb) are under development and they will be released in version 2.0.
153
+
154
+ ###
155
+
156
+ %Declaration
157
+
158
+ #(welcome_message)[@(name),@(message)] = [Welcome **@(name)**,@(message)] %should be
159
+ %declared in the preamble
160
+
161
+ %Usage
162
+
163
+ #(welcome_message)[Adhithya Rajasekaran,Hello World] %This should output
164
+ %Welcome \textbf{Adhithya Rajasekaran}, Hello World
165
+
166
+ ###
167
+
168
+ #(cftb)[] can span multiple lines. Parameterless @(ftb) can be used as a constants spanning multiple lines.
169
+
170
+ ###
171
+
172
+ %Declaration
173
+
174
+ #(disclaimer_statement)[] = [**WARNING**: Computer viruses can be transmitted via email.
175
+ The recipient should check this email and any attachments for the presence of viruses.
176
+ The company accepts no liability for any damage caused by any virus transmitted by this email.
177
+ E-mail transmission cannot be guaranteed to be secure or error-free as information could be
178
+ intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses.
179
+ The sender therefore does not accept liability for any errors or omissions in the
180
+ contents of this message, which arise as a result of e-mail transmission.]
181
+ %must be declared in the preamble
182
+
183
+ %Usage
184
+
185
+ #(disclaimer_statement)[] %anywhere in the body
186
+
187
+ ###
188
+
189
+ \item **Formulas**: Formulas were inspired by *[ Homebrew's => http://www.mxcl.github.com/homebrew/] formulas. @(vfl) is shipped with very few formulas
190
+ and the number is slowly increasing. The formulas that are shipped with @(vfl) are written for tasks that are difficult to do with LaTex. All the formulas will accept
191
+ accept a variable as a parameter. Let us take a look into the formulas that ship with @(vfl)
192
+
193
+ \begin{enumerate}
194
+
195
+ \item **Matrix Formula**: Matrices are very hard to construct in LaTex even with **AMSMATH** package. So @(vfl) ships with a %%\$(matrix)[]%% formula that allows
196
+ for the easy creation of matrices. This formula will create a matrix with square brackets around it.Let us do an example
197
+
198
+ I want to create a matrix \vspace{5pt}
199
+
200
+ A = $(matrix)[1 2 3;4 5 6;7 8 9]
201
+
202
+ ###
203
+
204
+ %using AMSMATH package
205
+
206
+ A = $\begin{bmatrix} 1 & 2 & 3 \\\\ 4 & 5 & 6 \\\\ 7 & 8 & 9 \end{bmatrix}$
207
+
208
+ %using Vanilla formula $(matrix)[]
209
+
210
+ A = $(matrix)[1 2 3;4 5 6;7 8 9]
211
+
212
+ ###
213
+
214
+ @(vfl) compiled the %%\$(matrix)[]%% formula into AMSMATH's **bmatrix** environment.
215
+
216
+ \item **Determinant Formula**: Determinants are very similar to matrices except they use a straight line to enclose the contents of the matrix. @(vfl) ships with
217
+ the %%\$(det)[]%% formula that takes care of determinants. Let us see a quick demo of this feature
218
+
219
+ I want to create a determinant \vspace{5pt}
220
+
221
+ B = $(det)[1 2 3;4 5 6;7 8 9]
222
+
223
+ ###
224
+
225
+ %using AMSMATH package
226
+
227
+ B = $\begin{vmatrix} 1 & 2 & 3 \\\\ 4 & 5 & 6 \\\\ 7 & 8 & 9 \end{vmatrix}$
228
+
229
+ %using Vanilla formula $(matrix)[]
230
+
231
+ B = $(det)[1 2 3;4 5 6;7 8 9]
232
+
233
+ ###
234
+
235
+ @(vfl) compiled the %%\$(det)[]%% formula into AMSMATH's **vmatrix** environment.
236
+
237
+ \item **Capitalize Formula**: Capitalize is a fun formula that capitalizes the first letter of every word in a string that is passed to it. Let us see a demo of this feature
238
+
239
+ %%\$(cap)[this is a wonderful day]%% will yield $(cap)[this is a wonderful day]
240
+
241
+ \item **Image Formula**: Image formula adds support for utilizing images from any part of the computer. By default, LaTex requires images that need to included in the PDF to be present in the same directory as the .tex file. This was believed to cause additional unnecessary work in the part of user. So the formula allows any image from any part of the computer to be used in a .tex file. The formula takes the path of the image and a ruby styled hash of options to manipulate the image. Currently **:scale**,**:width**,**:height**,**:angle** and **:page** options are supported.
242
+ ###
243
+ Example Usage:
244
+
245
+ $(image)[C:\Users\Adhi\Desktop\sample.jpg,options = {:scale => 0.35}]
246
+
247
+ ###
248
+ This resolves *[issue 10 => https://github.com/adhithyan15/vanilla/issues/10] on project page.
249
+
250
+ \end{enumerate}
251
+
252
+ As you can see that the number of formulas are very limited. Version 2.0 will allow users to create their own formulas using Ruby.
253
+
254
+ \item **Inline Calculations**: Inline calculations allow you to perform simple yet powerful calculations with in the document. You can have to nest your calculations inside ![] to perform the calculations. Let us see an example \vspace{5pt}
255
+
256
+ **%%![5*(45*(60/2))+3]%%** compiles into **![5*(45*(60/2))+3]**
257
+
258
+ \item **Inline Formatting**: Formatting is made easy by @(vfl). There are several formatting options provided by @(vfl). We will look at each one of them individually
259
+
260
+ \begin{enumerate}
261
+
262
+ \item **Boldface**: You can boldface any text using %%**some text**%% and it will output **some text**.
263
+
264
+ \item **Italicize**: You can italicize any text using %%///some text///%% and it will output ///some text///.
265
+
266
+ \item **Underline**: You can underline any text using **three underscores** on either side. Example: ___some text___ .
267
+
268
+ \item **Strikeout**: You can strikeout any text using **three tildes**. Example: ~~~2012~~~2013.
269
+
270
+ \end{enumerate}
271
+
272
+ \item **Tex Packs**: Tex Packs allow users to abstract away their most used LaTex packages into a file with any name and an extension .texpack. You can then import these Tex Packs into your @(vfl) documents by using %%\$(importpack)[package location]%% in your preamble. Tex Packs are designed to encourage reusability and seperating the structure of the document from the content of the document. The LaTex packages that this document uses have been defined in a texpack called documentation.texpack. Please take a look into that to get an idea of how to write a .texpack.
273
+
274
+ There is no special syntax for defining a texpack. You can copy and paste all the usepackage statements into a texpack and import it using the importpack function.
275
+
276
+ @(vfl) allows beginners start typesetting documents without worrying about packages. If a document doesn't have any importpack function calls or any usepackage statements, then the preprocessor will automatically add some of the most used packages to the document. The following are the packages provided out of the box by @(vfl).
277
+
278
+ \begin{enumerate}
279
+
280
+ \item Amsmath,Amssymb,Amsthm
281
+
282
+ \item Ulem with Normalem
283
+
284
+ \item Geometry with A4paper and 1.0in margin
285
+
286
+ \item Hyperref
287
+
288
+ \item Xcolor
289
+
290
+ \item Verbatim
291
+
292
+ \item Booktabs
293
+
294
+ \item Multicol
295
+
296
+ \item Graphicx
297
+
298
+ \item Siunitx
299
+
300
+ \item Cleveref
301
+
302
+ \end{enumerate}
303
+
304
+ \item **Smarty Pants Features**: These features were inspired by *[Smarty Pants => http://daringfireball.net/projects/smartypants/].
305
+
306
+ \begin{enumerate}
307
+
308
+ \item **Ellipses**: You can use %%....%% to insert ellipses anywhere. @(vfl) will be compiled to LaTex's ldots command. For example %%To be continued ....%% will become To be continuted ....
309
+
310
+ \end{enumerate}
311
+
312
+ \item **URLs and Hyperlinks**: @(vfl) provides support for two kinds of URLs out of the box. @(vfl) calls them bare urls and descriptive urls. Let us take a look into both of them.
313
+
314
+ \begin{enumerate}
315
+
316
+ \item **Bare URLs**: With @(vfl), you can just type in your URL in the document and the preprocessor will automatically find it and convert it into a LaTex hyperlink.Let us see an example
317
+
318
+ %%http://github.com/adhithyan15%% will become http://github.com/adhithyan15
319
+
320
+ \item **Descriptive URLs**: Descriptive URLs allow a word or a phrase to be hyperlinked to an URL.@(vfl) comes with a simple syntax to write descriptive URLs easily. The syntax is **%%*[word or phrase =\textgreater URL]%%**.Let us see an example
321
+
322
+ %%*[blog =\textgreater http://adhithyaraja.wordpress.com]%% will become *[blog => http://adhithyaraja.wordpress.com].
323
+
324
+ \end{enumerate}
325
+
326
+ \item **Double Quotes**: In @(vfl), you can use %%'' ''%% to surround some text with double quotes. For example, %%''hello''%% will produce "hello".
327
+
328
+ \item **Building Vanilla from Source**: You can build Vanilla executable from source using Ruby.**This only works in windows**. Make sure that you have **Ocra** gem installed. Make the bin folder the current directory. Then call "ruby vanilla.rb -b file". This will make a new windows and unix executable.
329
+
330
+ \item **Undocumented Features**: There are couple of features which were included in the compiler just for the sake of writing this documentation. They are the fenced code block and inline code block. It is not possible to demonstrate their features here because they determine whether a piece of code gets compiled by the preprocessor. You can look inside the source of this document to know how they are used.
331
+
332
+ \end{itemize}
333
+
334
+ The project is licensed under MIT License. You can read the text of the license below.
335
+
336
+ \vspace{5pt}
337
+
338
+ **License**: Copyright 2013 Adhithya Rajasekaran, Renuka Rajasekaran, Sri Madhavi Rajasekaran and other contributors
339
+ http://adhithyan15.github.com/vanilla
340
+
341
+ \vspace{5pt}
342
+
343
+ Permission is hereby granted, free of charge, to any person obtaining
344
+ a copy of this software and associated documentation files (the
345
+ "Software"), to deal in the Software without restriction, including
346
+ without limitation the rights to use, copy, modify, merge, publish,
347
+ distribute, sublicense, and/or sell copies of the Software, and to
348
+ permit persons to whom the Software is furnished to do so, subject to
349
+ the following conditions:
350
+
351
+ \vspace{5pt}
352
+
353
+ The above copyright notice and this permission notice shall be
354
+ included in all copies or substantial portions of the Software.
355
+
356
+ \vspace{5pt}
357
+
358
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
359
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
360
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
361
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
362
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
363
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
364
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
365
+
366
+ \end{document}
@@ -0,0 +1,6 @@
1
+ \usepackage{amsmath,amssymb,amsthm}
2
+ \usepackage[a4paper,margin = 1in]{geometry}
3
+ \usepackage{hyperref}
4
+ \usepackage[normalem]{ulem}
5
+ \usepackage{graphicx}
6
+
data/lib/vfl.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "vfl/version"
2
+
3
+ module Vfl
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,3 @@
1
+ module Vfl
2
+ VERSION = "0.0.0.1"
3
+ end
data/src/vanilla.rb ADDED
@@ -0,0 +1,1819 @@
1
+ #Vanilla is a simple yet powerful preprocessor for LaTex
2
+ #
3
+ #The project is hosted at http://github.com/adhithyan15/vanilla
4
+ #
5
+ #This compiler is a translation of the original compiler written in Python. But a lot of algorithmic structure has been
6
+ #modified to give optimum performance.Some parts may be rewritten in the upcoming releases.
7
+ #
8
+ #The prototype compilers written in Matlab and Python are now available in the Old Compiler Prototypes directory
9
+ #
10
+ #Authors: Adhithya Rajasekaran and Sri Madhavi Rajasekaran
11
+ #
12
+ #To know more about the features implemented in this compiler, please read the documentation.
13
+ #
14
+ #Abbrevations: VAL => Vanilla Flavored LaTex
15
+
16
+ require 'FileUtils'
17
+
18
+ require 'optparse'
19
+
20
+ def start_compile(input_val_file) #This method starts the compilation process
21
+
22
+ def read_file_line_by_line(input_path)
23
+
24
+ #This method returns each line of the VAL file as a list
25
+
26
+ file_id = open(input_path)
27
+
28
+ file_line_by_line = file_id.readlines()
29
+
30
+ file_id.close
31
+
32
+ return file_line_by_line
33
+
34
+ end
35
+
36
+ #The following are undocumented features mostly written to write the documentation.
37
+
38
+ def replace_fenced_code_block(input_file_contents,input_val_file)
39
+
40
+ #Latex offers Verbatim mode through verbatim package to prevent code from execution.Fence code block extends the verbatim mode to include
41
+ #VAL code also. Verbatim package is a part of our default pack so you don't have to manually import and use it.
42
+
43
+ #This method replaces all the declared fenced code blocks with @@fenced_code_block[identifier]
44
+ #This is done to prevent compile time error prevention.
45
+
46
+ def find_all_matching_indices(input_string,pattern)
47
+
48
+ locations = []
49
+
50
+ index = input_string.index(pattern)
51
+
52
+ while index != nil
53
+
54
+ locations << index
55
+
56
+ index = input_string.index(pattern,index+1)
57
+
58
+
59
+ end
60
+
61
+ return locations
62
+
63
+
64
+ end
65
+
66
+ def find_val_file_path(input_path)
67
+
68
+ #This method is utilized to extract the path of the VAL file.
69
+
70
+ extension_remover = input_path.split(".tex")
71
+
72
+ remaining_string = extension_remover[0].reverse
73
+
74
+ path_finder = remaining_string.index("/")
75
+
76
+ remaining_string = remaining_string.reverse
77
+
78
+ return remaining_string[0...remaining_string.length-path_finder]
79
+
80
+ end
81
+
82
+ input_file_as_string = input_file_contents.join
83
+
84
+ modified_input_string = input_file_as_string.dup
85
+
86
+ preferred_directory = find_val_file_path(input_val_file)
87
+
88
+ locate_fenced_code_block = find_all_matching_indices(input_file_as_string,"###")
89
+
90
+ fenced_code_block = []
91
+
92
+ start_location = 0
93
+
94
+ end_location = 1
95
+
96
+ if locate_fenced_code_block.length.modulo(2) == 0
97
+
98
+ for x in 0...locate_fenced_code_block.length/2
99
+
100
+ fenced_code_block_string = input_file_as_string[locate_fenced_code_block[start_location]..locate_fenced_code_block[end_location]+2]
101
+
102
+ fenced_code_block << fenced_code_block_string
103
+
104
+ replacement_string = "@@fenced_code_block[#{x+1}]"
105
+
106
+ modified_input_string = modified_input_string.sub(fenced_code_block_string,replacement_string)
107
+
108
+ start_location = start_location + 2
109
+
110
+ end_location = end_location + 2
111
+
112
+ end
113
+
114
+ end
115
+
116
+ temporary_file_path = find_val_file_path(input_val_file) + "temp.tex"
117
+
118
+ file_id = open(temporary_file_path, 'w')
119
+
120
+ file_id.write(modified_input_string)
121
+
122
+ file_id.close()
123
+
124
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
125
+
126
+ return line_by_line_contents, temporary_file_path, fenced_code_block,preferred_directory
127
+
128
+ end
129
+
130
+ def replace_inline_fenced_code(input_file_contents,temporary_file_path)
131
+
132
+ #This method will prevent inline VAL code from being compiled. This will only prevent VAL code from being
133
+ #compiled. If the inline code contains LaTex code, then LaTex compiler will compile it into PDF.
134
+ #This method was mainly written for presenting VAL code in the Vanilla documentation.
135
+
136
+ #This uses the same methodology as the fenced code block. Tt replaces inline code blocks with
137
+ #@@inline_code_bloc[identifier]
138
+
139
+ def find_all_matching_indices(input_string,pattern)
140
+
141
+ locations = []
142
+
143
+ index = input_string.index(pattern)
144
+
145
+ while index != nil
146
+
147
+ locations << index
148
+
149
+ index = input_string.index(pattern,index+1)
150
+
151
+
152
+ end
153
+
154
+ return locations
155
+
156
+
157
+ end
158
+
159
+ input_file_as_string = input_file_contents.join
160
+
161
+ modified_input_string = input_file_as_string.dup
162
+
163
+ locate_inline_code_block = find_all_matching_indices(input_file_as_string,"%%")
164
+
165
+ inline_code_block = []
166
+
167
+ start_location = 0
168
+
169
+ end_location = 1
170
+
171
+ if locate_inline_code_block.length.modulo(2) == 0
172
+
173
+ for x in 0...locate_inline_code_block.length/2
174
+
175
+ inline_code_block_string = input_file_as_string[locate_inline_code_block[start_location]..locate_inline_code_block[end_location]+1]
176
+
177
+ inline_code_block << inline_code_block_string
178
+
179
+ replacement_string = "@@inline_code_block[#{x+1}]"
180
+
181
+ modified_input_string = modified_input_string.sub(inline_code_block_string,replacement_string)
182
+
183
+ start_location = start_location + 2
184
+
185
+ end_location = end_location + 2
186
+
187
+ end
188
+
189
+ end
190
+
191
+ file_id = open(temporary_file_path, 'w')
192
+
193
+ file_id.write(modified_input_string)
194
+
195
+ file_id.close()
196
+
197
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
198
+
199
+ return line_by_line_contents, temporary_file_path, inline_code_block
200
+
201
+ end
202
+
203
+ #The following features are documented features.
204
+
205
+ def resolve_comments(input_file_contents,temporary_file_path)
206
+
207
+ #Latex does offer support for multiline comments. But VAL makes the process easier. This method compiles
208
+ #VAL multiline comments into several single line latex comments.Latex comments are still valid in VAL.
209
+
210
+ def find_all_matching_indices(input_string,pattern)
211
+
212
+ locations = []
213
+
214
+ index = input_string.index(pattern)
215
+
216
+ while index != nil
217
+
218
+ locations << index
219
+
220
+ index = input_string.index(pattern,index+1)
221
+
222
+
223
+ end
224
+
225
+ return locations
226
+
227
+
228
+ end
229
+
230
+ input_file_as_string = input_file_contents.join
231
+
232
+ modified_input_string = input_file_as_string.dup
233
+
234
+ location_of_multiline_comments_start = find_all_matching_indices(input_file_as_string,"%{")
235
+
236
+ location_of_multiline_comments_end = find_all_matching_indices(input_file_as_string,"}%")
237
+
238
+ if location_of_multiline_comments_start.length == location_of_multiline_comments_end.length
239
+
240
+ for x in 0...location_of_multiline_comments_start.length
241
+
242
+ multiline_comment = input_file_as_string[location_of_multiline_comments_start[x]..location_of_multiline_comments_end[x]+1]
243
+
244
+ replacement_comment = multiline_comment.sub("%{","")
245
+
246
+ replacement_comment = replacement_comment.sub("}%","")
247
+
248
+ multiline_comment_split = replacement_comment.split("\n")
249
+
250
+ for y in 0...multiline_comment_split.length
251
+
252
+ multiline_comment_split[y] = "%" + multiline_comment_split[y]
253
+
254
+ end
255
+
256
+ replacement_comment = multiline_comment_split.join("\n")
257
+
258
+ modified_input_string = modified_input_string.sub(multiline_comment,replacement_comment)
259
+
260
+
261
+ end
262
+
263
+ end
264
+
265
+ file_id = open(temporary_file_path, 'w')
266
+
267
+ file_id.write(modified_input_string)
268
+
269
+ file_id.close()
270
+
271
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
272
+
273
+ return line_by_line_contents, temporary_file_path
274
+
275
+ end
276
+
277
+ def resolve_constants(input_file_contents, temporary_file_path)
278
+
279
+ #Latex does offer support for declaring constants. But VAL greatly simplifies the process of declaring those constants.
280
+ #You can still use latex constants.
281
+
282
+ #Note:VAL constants are not transformed into Latex constants. Constants stand for what they mean.They are immutable.
283
+ #Pure mutable variables may be available in VAL in the future. Lexical Scoping of constants is similar to that in
284
+ #programming languages. This would be imminent in the code block resolution method.
285
+
286
+ #Updates 2/16/2012 -> Constants now support what our user called "Computed Properties". So users can now include
287
+ #calculations and reference other constants while declaring constants.
288
+
289
+ def retrieve_constants(input_file_contents)
290
+
291
+ #This method looks into the preamble of the document and picks up all the constant declarations. Then it splits and
292
+ #produces an array of constant names and constant values.
293
+
294
+ end_of_preamble = 0
295
+
296
+ if input_file_contents.include?("\\begin{document}\n")
297
+
298
+ end_of_preamble = input_file_contents.index("\\begin{document}\n")
299
+
300
+ end
301
+
302
+ preamble = input_file_contents[0...end_of_preamble]
303
+
304
+ modified_preamble = preamble.dup
305
+
306
+ length_of_preamble = preamble.length
307
+
308
+ variable_list = []
309
+
310
+ for x in 0...length_of_preamble
311
+
312
+ current_row = preamble[x]
313
+
314
+ if !current_row.include?("%")
315
+
316
+ if !current_row.include?("#")
317
+
318
+ if current_row.include?("@")
319
+
320
+ if current_row.index("@") == 0
321
+
322
+ if current_row.split("=").length() == 2
323
+
324
+ modified_preamble.delete(current_row)
325
+
326
+ variable_list << current_row.strip
327
+
328
+ end
329
+
330
+ end
331
+
332
+ end
333
+
334
+ end
335
+
336
+ else
337
+
338
+ inline_comment_finder = current_row.index("%")
339
+
340
+ operating_string = current_row[0...inline_comment_finder]
341
+
342
+ if !operating_string.include?("#")
343
+
344
+ if operating_string.include?("@")
345
+
346
+ if operating_string.index("@") == 0
347
+
348
+ if operating_string.split("=").length() == 2
349
+
350
+ modified_preamble.delete(current_row)
351
+
352
+ variable_list << operating_string.strip
353
+
354
+ end
355
+
356
+ end
357
+
358
+ end
359
+
360
+ end
361
+
362
+ end
363
+
364
+ end
365
+
366
+ variable_names = []
367
+
368
+ variable_values = []
369
+
370
+ for y in 0...variable_list.length
371
+
372
+ current_row = variable_list[y]
373
+
374
+ variable_name_and_value = current_row.split("=")
375
+
376
+ variable_names << variable_name_and_value[0].strip
377
+
378
+ variable_values << variable_name_and_value[1].strip
379
+
380
+
381
+ end
382
+
383
+ modified_variable_values = []
384
+
385
+ variable_values.each do |value|
386
+
387
+ if value.include? "@("
388
+
389
+ new_value = value.dup
390
+
391
+ variable_names.each do |name|
392
+
393
+ if new_value.include? name
394
+
395
+ new_value = new_value.sub(name,variable_values[variable_names.index(name)])
396
+
397
+ end
398
+
399
+ end
400
+
401
+ ruby_binding = binding
402
+
403
+ val = ruby_binding.eval(new_value).to_s
404
+
405
+ modified_variable_values << val
406
+
407
+ else
408
+
409
+ modified_variable_values << value
410
+
411
+ end
412
+
413
+ end
414
+
415
+ return variable_names, modified_variable_values, modified_preamble
416
+
417
+ end
418
+
419
+ variable_names, variable_values, preamble = retrieve_constants(input_file_contents)
420
+
421
+ end_of_preamble = 0
422
+
423
+ if input_file_contents.include?("\\begin{document}\n")
424
+
425
+ end_of_preamble = input_file_contents.index("\\begin{document}\n")
426
+
427
+ end
428
+
429
+ document_body = input_file_contents[end_of_preamble..-1].join
430
+
431
+ for x in 0...variable_names.length
432
+
433
+ current_variable = variable_names[x]
434
+
435
+ document_body = document_body.gsub(current_variable, variable_values[x])
436
+
437
+ end
438
+
439
+ file_id = open(temporary_file_path, 'w')
440
+
441
+ file_id.write(preamble.join+document_body)
442
+
443
+ file_id.close()
444
+
445
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
446
+
447
+ return line_by_line_contents, temporary_file_path
448
+
449
+
450
+ end
451
+
452
+ def resolve_formatted_text_blocks(input_file_contents,temporary_file_path)
453
+
454
+ #This method will resolve formatted text blocks. The idea of formatted code blocks was inspired by Lesscss' parametric mixins.
455
+
456
+ #Latex doesn't offer support for formatted text blocks. So VAL provides support for it.
457
+
458
+ def retrieve_formatted_text_blocks(input_file_contents)
459
+
460
+ #This method will go through the preamble and will retrieve a list of declared formatted text blocks
461
+
462
+ def remove_comments(input_string)
463
+
464
+ #This method will remove comments from a string.This method is part of a large rewrite operation to reduce the clutter
465
+ #in the code and also to increase performance
466
+
467
+ if input_string.include?("%")
468
+
469
+ output_string = input_string[0...input_string.index("%")]
470
+
471
+ else
472
+
473
+ output_string = input_string
474
+
475
+ end
476
+
477
+ return output_string
478
+
479
+ end
480
+
481
+ end_of_preamble = 0
482
+
483
+ if input_file_contents.include?("\\begin{document}\n")
484
+
485
+ end_of_preamble = input_file_contents.index("\\begin{document}\n")
486
+
487
+ end
488
+
489
+ preamble = input_file_contents[0...end_of_preamble]
490
+
491
+ modified_preamble = preamble.dup
492
+
493
+ length_of_preamble = preamble.length
494
+
495
+ text_blocks_list = []
496
+
497
+ for x in 0...preamble.length
498
+
499
+ current_row = preamble[x]
500
+
501
+ if current_row.include?("#")
502
+
503
+ if current_row.include?("%")
504
+
505
+ operating_string = current_row[0...current_row.index("%")]
506
+
507
+ comment_string = current_row[current_row.index("%")..-1]
508
+
509
+ else
510
+
511
+ operating_string = current_row
512
+
513
+ comment_string = ""
514
+
515
+ end
516
+
517
+ text_block_finder = operating_string.split("=")
518
+
519
+ if text_block_finder.length > 1
520
+
521
+ if text_block_finder[1].include?("[")
522
+
523
+ if text_block_finder[1].include?("]")
524
+
525
+ code_block = [operating_string]
526
+
527
+ modified_preamble.delete(operating_string+comment_string)
528
+
529
+ text_blocks_list << code_block.join("")
530
+
531
+ else
532
+
533
+ next_index = x
534
+
535
+ code_block = []
536
+
537
+ text_block_end_finder = text_block_finder[1].include?("]")
538
+
539
+ while text_block_end_finder == false
540
+
541
+ code_block << preamble[next_index]
542
+
543
+ modified_preamble.delete(preamble[next_index])
544
+
545
+ next_index = next_index + 1
546
+
547
+ text_block_end_finder = preamble[next_index].include?("]")
548
+
549
+ end
550
+
551
+ code_block << remove_comments(preamble[next_index])
552
+
553
+ modified_preamble.delete(preamble[next_index])
554
+
555
+ text_blocks_list << code_block.join("")
556
+
557
+
558
+ end
559
+
560
+ end
561
+
562
+ end
563
+
564
+ end
565
+
566
+ end
567
+
568
+ code_block_names = []
569
+
570
+ code_block_values = []
571
+
572
+ for x in 0...text_blocks_list.length
573
+
574
+ current_text_block = text_blocks_list[x]
575
+
576
+ text_block_name_and_value = current_text_block.split("=")
577
+
578
+ code_block_names << text_block_name_and_value[0].strip
579
+
580
+ code_block_values << text_block_name_and_value[1].strip
581
+
582
+ end
583
+
584
+ return code_block_names,code_block_values,modified_preamble
585
+
586
+ end
587
+
588
+ def extract_parameters(names_with_params)
589
+
590
+ code_block_names = []
591
+
592
+ code_block_params = []
593
+
594
+ for x in 0...names_with_params.length
595
+
596
+ current_code_block_name = names_with_params[x]
597
+
598
+ params_split = current_code_block_name.split("[")
599
+
600
+ code_block_names << params_split[0]
601
+
602
+ params_list = params_split[1]
603
+
604
+ params_list = params_list[0...-1]
605
+
606
+ code_block_params << params_list
607
+
608
+ end
609
+
610
+ return code_block_names,code_block_params
611
+
612
+ end
613
+
614
+ def find_all_matching_indices(input_string,pattern)
615
+
616
+ locations = []
617
+
618
+ index = input_string.index(pattern)
619
+
620
+ while index != nil
621
+
622
+ locations << index
623
+
624
+ index = input_string.index(pattern,index+1)
625
+
626
+
627
+ end
628
+
629
+ return locations
630
+
631
+
632
+ end
633
+
634
+ block_names_params,code_block_values,preamble = retrieve_formatted_text_blocks(input_file_contents)
635
+
636
+ code_block_names,code_block_params = extract_parameters(block_names_params)
637
+
638
+ end_of_preamble = 0
639
+
640
+ if input_file_contents.include?("\\begin{document}\n")
641
+
642
+ end_of_preamble = input_file_contents.index("\\begin{document}\n")
643
+
644
+ end
645
+
646
+ document_body = input_file_contents[end_of_preamble..-1]
647
+
648
+ document_body_as_string = document_body.join("")
649
+
650
+ modified_document_as_string = document_body_as_string.dup
651
+
652
+ for x in 0...code_block_names.length
653
+
654
+ current_code_block_name = code_block_names[x]
655
+
656
+ current_code_block_params = code_block_params[x]
657
+
658
+ current_code_block_params = current_code_block_params.split(",")
659
+
660
+ current_code_block_value = code_block_values[x]
661
+
662
+ current_code_block_value = current_code_block_value[1...-1]
663
+
664
+ location_of_code_block = find_all_matching_indices(document_body_as_string,current_code_block_name)
665
+
666
+ for y in 0...location_of_code_block.length
667
+
668
+ code_block_end_finder = document_body_as_string.index("]",location_of_code_block[y])
669
+
670
+ text_block_string = document_body_as_string[location_of_code_block[y]..code_block_end_finder]
671
+
672
+ param_split = text_block_string.split("[")
673
+
674
+ text_block_params = param_split[1]
675
+
676
+ text_block_params = text_block_params[0...-1]
677
+
678
+ text_block_params = text_block_params.split(",")
679
+
680
+ if text_block_params.length == current_code_block_params.length
681
+
682
+ parameter_map = Hash[*current_code_block_params.zip(text_block_params).flatten]
683
+
684
+ replacement_string = current_code_block_value
685
+
686
+ for z in 0...parameter_map.length
687
+
688
+ replacement_string = replacement_string.gsub(current_code_block_params[z],parameter_map[current_code_block_params[z]])
689
+
690
+ end
691
+
692
+ modified_document_as_string = modified_document_as_string.sub(text_block_string,replacement_string)
693
+
694
+ end
695
+
696
+ end
697
+
698
+ end
699
+
700
+ file_id = open(temporary_file_path, 'w')
701
+
702
+ file_id.write(preamble.join+modified_document_as_string)
703
+
704
+ file_id.close()
705
+
706
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
707
+
708
+ return line_by_line_contents, temporary_file_path
709
+
710
+ end
711
+
712
+ def resolve_formulas(input_file_contents,temporary_file_path)
713
+
714
+ #VAL Formulas are easy way to achieve certain things which are very difficult to achieve in Latex. Writing matrices
715
+ #is very difficult in latex. As time progresses, more formulas will be added to simplify latex typesetting.
716
+
717
+ def find_all_matching_indices(input_string,pattern)
718
+
719
+ locations = []
720
+
721
+ index = input_string.index(pattern)
722
+
723
+ while index != nil
724
+
725
+ locations << index
726
+
727
+ index = input_string.index(pattern,index+1)
728
+
729
+
730
+ end
731
+
732
+ return locations
733
+
734
+
735
+ end
736
+
737
+ def convert_to_matrix(input_list)
738
+
739
+ #This method converts the input list to latex's bmatrix environment offered through amsmath package.
740
+
741
+ start_string = "$\\begin{bmatrix}"
742
+
743
+ end_string = "\\end{bmatrix}$"
744
+
745
+ rows = []
746
+
747
+ for x in 0...input_list.length
748
+
749
+ current_row = input_list[x]
750
+
751
+ current_row_string = current_row.split.join(" & ")
752
+
753
+ rows << current_row_string
754
+
755
+
756
+ end
757
+
758
+ matrix = rows.join(" \\\\\\\\\\\\\\\\ ")
759
+
760
+ matrix = "$" + start_string + matrix + end_string + "$"
761
+
762
+ return matrix
763
+
764
+ end
765
+
766
+ def convert_to_determinant(input_list)
767
+
768
+ #This method converts the input list to latex's vmatrix environment offered through amsmath package.
769
+
770
+ start_string = "\\begin{vmatrix}"
771
+
772
+ end_string = "\\end{vmatrix}"
773
+
774
+ rows = []
775
+
776
+ for x in 0...input_list.length
777
+
778
+ current_row = input_list[x]
779
+
780
+ current_row_string = current_row.split.join(" & ")
781
+
782
+ rows << current_row_string
783
+
784
+
785
+ end
786
+
787
+ determinant = rows.join(" \\\\\\\\\\\\\\\\ ")
788
+
789
+ determinant = "$" + start_string + determinant + end_string + "$"
790
+
791
+ return determinant
792
+
793
+ end
794
+
795
+ def capitalize(input_string)
796
+
797
+ #This method will capitalize every single word in a string
798
+
799
+ input_string_split = input_string.split
800
+
801
+ for x in 0...input_string_split.length
802
+
803
+ current_word = input_string_split[x]
804
+
805
+ if current_word.length > 1
806
+
807
+ current_word = current_word[0].upcase + current_word[1..-1]
808
+
809
+ else
810
+
811
+ current_word = current_word.upcase
812
+
813
+ end
814
+
815
+ input_string_split[x] = current_word
816
+
817
+ end
818
+
819
+ return input_string_split.join(" ")
820
+
821
+ end
822
+
823
+ def image(input_string_split,temp_file_path)
824
+
825
+ def find_file_path(input_path,file_extension)
826
+
827
+ extension_remover = input_path.split(file_extension)
828
+
829
+ remaining_string = extension_remover[0].reverse
830
+
831
+ if remaining_string.include?("\\")
832
+
833
+ path_finder = remaining_string.index("\\")
834
+
835
+ elsif remaining_string.include?("/")
836
+
837
+ path_finder = remaining_string.index("/")
838
+
839
+ end
840
+
841
+ remaining_string = remaining_string.reverse
842
+
843
+ return remaining_string[0...remaining_string.length-path_finder]
844
+
845
+ end
846
+
847
+ def find_file_name(input_path,file_extension)
848
+
849
+ extension_remover = input_path.split(file_extension)
850
+
851
+ remaining_string = extension_remover[0].reverse
852
+
853
+ path_finder = remaining_string.index("\\")
854
+
855
+ remaining_string = remaining_string.reverse
856
+
857
+ return remaining_string[remaining_string.length-path_finder..-1]
858
+
859
+ end
860
+
861
+ def find_file_extension(input_path)
862
+
863
+ extension_start = input_path.index(".")
864
+
865
+ return input_path[extension_start..-1]
866
+
867
+ end
868
+
869
+ available_options = ["scale","width","height","angle","page"]
870
+
871
+ image_path = input_string_split[0]
872
+
873
+ options = input_string_split[1]
874
+
875
+ current_destination = find_file_path(image_path,find_file_extension(image_path))
876
+
877
+ to_be_moved_destination = find_file_path(temp_file_path,".tex")
878
+
879
+ to_be_moved_dest = to_be_moved_destination + "/#{find_file_name(image_path,"#{find_file_extension(image_path)}")}#{find_file_extension(image_path)}"
880
+
881
+ if !current_destination.eql? to_be_moved_destination
882
+
883
+ FileUtils.cp image_path,to_be_moved_dest
884
+
885
+ eval_binding = binding
886
+
887
+ options_hash = eval_binding.eval(options)
888
+
889
+ option_values = []
890
+
891
+ available_options.each do |option|
892
+
893
+ if options_hash.has_key?(option.to_sym)
894
+
895
+ option_values << option + " = #{options_hash[option.to_sym]}"
896
+
897
+ end
898
+
899
+ end
900
+
901
+ return_string = "\\\\includegraphics[#{option_values.join(",")}]{#{find_file_name(image_path,"#{find_file_extension(image_path)}")}}"
902
+
903
+ else
904
+
905
+ eval_binding = binding
906
+
907
+ options_hash = eval_binding.eval(options)
908
+
909
+ option_values = []
910
+
911
+ available_options.each do |option|
912
+
913
+ option_values << option + " = #{options_hash[option.to_sym]}"
914
+
915
+ end
916
+
917
+ return_string = "\\\\includegraphics[#{option_values.join(",")}]{#{find_file_name(image_path,".#{find_file_extension(image_path)}")}}"
918
+
919
+ end
920
+
921
+ return return_string
922
+
923
+
924
+ end
925
+
926
+ available_formulas = ["$(matrix)","$(det)","$(cap)","$(image)"]
927
+
928
+ input_file_as_string = input_file_contents.join
929
+
930
+ modified_input_string = input_file_as_string.dup
931
+
932
+ for x in 0...available_formulas.length
933
+
934
+ current_formula = available_formulas[x]
935
+
936
+ location_of_current_formula = find_all_matching_indices(input_file_as_string,current_formula)
937
+
938
+ for y in 0...location_of_current_formula.length
939
+
940
+ replacement_string = ""
941
+
942
+ extract_string = input_file_as_string[location_of_current_formula[y]..-1]
943
+
944
+ current_formula_end = extract_string.index("]")
945
+
946
+ formula_usage_string = extract_string[0..current_formula_end]
947
+
948
+ formula_usage_string_split = formula_usage_string.split("[")
949
+
950
+ formula_usage_string_split = formula_usage_string_split[1].split("]")
951
+
952
+ if x == 0
953
+
954
+ formula_usage_string_split = formula_usage_string_split[0].split(";")
955
+
956
+ replacement_string = convert_to_matrix(formula_usage_string_split)
957
+
958
+ elsif x == 1
959
+
960
+ formula_usage_string_split = formula_usage_string_split[0].split(";")
961
+
962
+ replacement_string = convert_to_determinant(formula_usage_string_split)
963
+
964
+ elsif x == 2
965
+
966
+ replacement_string = capitalize(formula_usage_string_split[0])
967
+
968
+
969
+ elsif x == 3
970
+
971
+ replacement_string = image(formula_usage_string_split[0].split(","),temporary_file_path)
972
+
973
+ end
974
+
975
+ modified_input_string = modified_input_string.sub(formula_usage_string,replacement_string)
976
+
977
+ end
978
+
979
+ end
980
+
981
+ file_id = open(temporary_file_path, 'w')
982
+
983
+ file_id.write(modified_input_string)
984
+
985
+ file_id.close()
986
+
987
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
988
+
989
+ return line_by_line_contents, temporary_file_path
990
+
991
+ end
992
+
993
+ def resolve_inline_calculations(input_file_contents,temporary_file_path)
994
+
995
+ #This method is used in converting inline calculations into answers. It uses ruby's eval method to achieve this.
996
+
997
+ def find_all_matching_indices(input_string,pattern)
998
+
999
+ locations = []
1000
+
1001
+ index = input_string.index(pattern)
1002
+
1003
+ while index != nil
1004
+
1005
+ locations << index
1006
+
1007
+ index = input_string.index(pattern,index+1)
1008
+
1009
+
1010
+ end
1011
+
1012
+ return locations
1013
+
1014
+
1015
+ end
1016
+
1017
+ for x in 0...input_file_contents.length
1018
+
1019
+ current_row = input_file_contents[x]
1020
+
1021
+ operating_row = current_row.dup
1022
+
1023
+ comment_string = ""
1024
+
1025
+ if current_row.include?("%")
1026
+
1027
+ operating_row = current_row[0...current_row.index("%")]
1028
+
1029
+ comment_string = current_row[current_row.index("%")...-1]
1030
+
1031
+ end
1032
+
1033
+ inline_calculation_strings = operating_row.match /!\[.{1,}\]/
1034
+
1035
+ inline_calculation_strings = inline_calculation_strings.to_a
1036
+
1037
+ for y in 0...inline_calculation_strings.length
1038
+
1039
+ inline_calculation_string = inline_calculation_strings[y]
1040
+
1041
+ inline_calc_ruby_string = inline_calculation_string.dup
1042
+
1043
+ inline_calc_ruby_string = inline_calc_ruby_string[2...-1]
1044
+
1045
+ inline_calc_ruby_string = inline_calc_ruby_string.sub("^","**").to_s()
1046
+
1047
+ eval_binding = binding
1048
+
1049
+ inline_calculation_answer = eval_binding.eval(inline_calc_ruby_string)
1050
+
1051
+ inline_calculation_answer = inline_calculation_answer.to_s
1052
+
1053
+ if inline_calculation_answer.include?(".")
1054
+
1055
+ inline_calculation_answer = inline_calculation_answer.to_f.round(3).to_s
1056
+
1057
+ end
1058
+
1059
+ current_row = current_row.sub(inline_calculation_string,inline_calculation_answer)
1060
+
1061
+ end
1062
+
1063
+ input_file_contents[x] = current_row
1064
+
1065
+ end
1066
+
1067
+ file_id = open(temporary_file_path, 'w')
1068
+
1069
+ file_id.write(input_file_contents.join)
1070
+
1071
+ file_id.close()
1072
+
1073
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
1074
+
1075
+ return line_by_line_contents, temporary_file_path
1076
+
1077
+ end
1078
+
1079
+ def resolve_inline_formatting(input_file_contents,temporary_file_path)
1080
+
1081
+ def find_all_matching_indices(input_string,pattern)
1082
+
1083
+ locations = []
1084
+
1085
+ index = input_string.index(pattern)
1086
+
1087
+ while index != nil
1088
+
1089
+ locations << index
1090
+
1091
+ index = input_string.index(pattern,index+1)
1092
+
1093
+
1094
+ end
1095
+
1096
+ return locations
1097
+
1098
+
1099
+ end
1100
+
1101
+ document_as_string = input_file_contents.join
1102
+
1103
+ available_formatting = ["**","///","+*","+/","___","~~~"]
1104
+
1105
+ matching_formatting = {"**" => "\\textbf{","///" => "\\emph{" , "+*" => "\\mathbf{" , "+/" => "\\mathit{", "___" => "\\underline{","~~~" => "\\sout{"}
1106
+
1107
+ for x in 0...available_formatting.length
1108
+
1109
+ current_formatting = available_formatting[x]
1110
+
1111
+ location_of_current_formatting = find_all_matching_indices(document_as_string,current_formatting)
1112
+
1113
+ if location_of_current_formatting.length.modulo(2) == 0
1114
+
1115
+ for y in 0...((location_of_current_formatting.length)/2)
1116
+
1117
+ document_as_string = document_as_string.sub(current_formatting,matching_formatting[current_formatting])
1118
+
1119
+ document_as_string = document_as_string.sub(current_formatting,"}")
1120
+
1121
+ end
1122
+
1123
+ end
1124
+
1125
+ end
1126
+
1127
+ file_id = open(temporary_file_path, 'w')
1128
+
1129
+ file_id.write(document_as_string)
1130
+
1131
+ file_id.close()
1132
+
1133
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
1134
+
1135
+ return line_by_line_contents, temporary_file_path
1136
+
1137
+ end
1138
+
1139
+ def resolve_fenced_code_blocks(input_file_contents,temporary_file_path,fenced_code_blocks)
1140
+
1141
+ input_file_as_string = input_file_contents.join
1142
+
1143
+ for x in 0...fenced_code_blocks.length
1144
+
1145
+ fenced_code_block_string = "@@fenced_code_block[#{x+1}]"
1146
+
1147
+ replacement_string = fenced_code_blocks[x]
1148
+
1149
+ replacement_string = replacement_string.sub("###","\\begin{verbatim}")
1150
+
1151
+ replacement_string = replacement_string.sub("###","\\end{verbatim}")
1152
+
1153
+ input_file_as_string = input_file_as_string.sub(fenced_code_block_string,replacement_string)
1154
+
1155
+ end
1156
+
1157
+ file_id = open(temporary_file_path, 'w')
1158
+
1159
+ file_id.write(input_file_as_string)
1160
+
1161
+ file_id.close()
1162
+
1163
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
1164
+
1165
+ return line_by_line_contents, temporary_file_path
1166
+
1167
+
1168
+ end
1169
+
1170
+ def resolve_inline_fenced_code(input_file_contents,temporary_file_path,inline_code_blocks)
1171
+
1172
+ input_file_as_string = input_file_contents.join
1173
+
1174
+ for x in 0...inline_code_blocks.length
1175
+
1176
+ fenced_code_block_string = "@@inline_code_block[#{x+1}]"
1177
+
1178
+ replacement_string = inline_code_blocks[x]
1179
+
1180
+ input_file_as_string = input_file_as_string.sub(fenced_code_block_string,replacement_string[2...-2])
1181
+
1182
+ end
1183
+
1184
+ file_id = open(temporary_file_path, 'w')
1185
+
1186
+ file_id.write(input_file_as_string)
1187
+
1188
+ file_id.close()
1189
+
1190
+ line_by_line_contents = read_file_line_by_line(temporary_file_path)
1191
+
1192
+ return line_by_line_contents, temporary_file_path
1193
+
1194
+
1195
+ end
1196
+
1197
+
1198
+ def resolve_tex_packs(input_file_contents,temporary_file,preference_directory)
1199
+
1200
+ def find_all_matching_indices(input_string,pattern)
1201
+
1202
+ locations = []
1203
+
1204
+ index = input_string.index(pattern)
1205
+
1206
+ while index != nil
1207
+
1208
+ locations << index
1209
+
1210
+ index = input_string.index(pattern,index+1)
1211
+
1212
+
1213
+ end
1214
+
1215
+ return locations
1216
+
1217
+
1218
+ end
1219
+
1220
+ default_texpack = [
1221
+ "\\usepackage{amsmath,amssymb,amsthm}\n\n",
1222
+ "\\usepackage[a4paper,margin = 1in]{geometry}\n\n",
1223
+ "\\usepackage{hyperref}\n\n",
1224
+ "\\usepackage[normalem]{ulem}\n\n",
1225
+ "\\usepackage{xcolor}\n\n",
1226
+ "\\usepackage{verbatim}\n\n",
1227
+ "\\usepackage{booktabs}\n\n",
1228
+ "\\usepackage{graphicx}\n\n",
1229
+ "\\usepackage{multicol}\n\n",
1230
+ "\\usepackage{cleveref}\n\n",
1231
+ "\\usepackage{siunitx}\n"]
1232
+
1233
+ end_of_preamble = 0
1234
+
1235
+ if input_file_contents.include?("\\begin{document}\n")
1236
+
1237
+ end_of_preamble = input_file_contents.index("\\begin{document}\n")
1238
+
1239
+ end
1240
+
1241
+ preamble = input_file_contents[0...end_of_preamble]
1242
+
1243
+ document_string = input_file_contents[end_of_preamble..-1].join
1244
+
1245
+ preamble_string = preamble.join
1246
+
1247
+ if !preamble_string.include?("$(importpack)") and !preamble_string.include?("\\usepackage")
1248
+
1249
+ default_texpack_string = default_texpack.join
1250
+
1251
+ documentclass_finder = preamble_string.index("\\documentclass")
1252
+
1253
+ extract_string = preamble_string[documentclass_finder..-1]
1254
+
1255
+ documentclass_end = extract_string.index("}")
1256
+
1257
+ documentclass_string = extract_string[0..documentclass_end]
1258
+
1259
+ replacement_string = documentclass_string + "\n\n" + default_texpack_string + "\n\n"
1260
+
1261
+ preamble_string = preamble_string.sub(documentclass_string,replacement_string)
1262
+
1263
+ elsif preamble_string.include?("$(importpack)")
1264
+
1265
+ importpack_locations = find_all_matching_indices(preamble_string,"$(importpack)")
1266
+
1267
+ for x in 0...importpack_locations.length
1268
+
1269
+ current_location = importpack_locations[x]
1270
+
1271
+ extract_string = preamble_string[current_location..-1]
1272
+
1273
+ importpack_end = extract_string.index("]")
1274
+
1275
+ importpack_string = extract_string[0..importpack_end]
1276
+
1277
+ importpack_string_split = importpack_string.split("[")
1278
+
1279
+ importpack_string_split = importpack_string_split[1].split("]")
1280
+
1281
+ importpack_name = importpack_string_split[0]
1282
+
1283
+ if !importpack_name.include?("\\")
1284
+
1285
+ importpack_path = preference_directory + importpack_name + ".texpack"
1286
+
1287
+ else
1288
+
1289
+ importpack_path = importpack_name
1290
+
1291
+ end
1292
+
1293
+ texpack_file = read_file_line_by_line(importpack_path).join
1294
+
1295
+ preamble_string = preamble_string.sub(importpack_string,texpack_file)
1296
+
1297
+
1298
+ end
1299
+
1300
+ end
1301
+
1302
+ file_id = open(temporary_file, 'w')
1303
+
1304
+ file_id.write(preamble_string + document_string)
1305
+
1306
+ file_id.close()
1307
+
1308
+ line_by_line_contents = read_file_line_by_line(temporary_file)
1309
+
1310
+ return line_by_line_contents, temporary_file
1311
+
1312
+
1313
+ end
1314
+
1315
+ def resolve_bare_urls(input_file_contents,temporary_file)
1316
+
1317
+ def find_all_matching_indices(input_string,pattern)
1318
+
1319
+ locations = []
1320
+
1321
+ index = input_string.index(pattern)
1322
+
1323
+ while index != nil
1324
+
1325
+ locations << index
1326
+
1327
+ index = input_string.index(pattern,index+1)
1328
+
1329
+
1330
+ end
1331
+
1332
+ return locations
1333
+
1334
+
1335
+ end
1336
+
1337
+ def modify_urls(input_url_string)
1338
+
1339
+ return_string = "\\url{#{input_url_string}}"
1340
+
1341
+ return return_string
1342
+
1343
+ end
1344
+
1345
+ input_file_as_string = input_file_contents.join
1346
+
1347
+ modified_input_string = input_file_as_string.dup
1348
+
1349
+ url_identifiers = ["http","www"]
1350
+
1351
+ replacements = ["@@http[]","@@www[]"]
1352
+
1353
+ identifier_matches = []
1354
+
1355
+ replacement_strings = []
1356
+
1357
+ for x in 0...url_identifiers.length
1358
+
1359
+ current_identifier = url_identifiers[x]
1360
+
1361
+ current_replacement = replacements[x]
1362
+
1363
+ current_replacement_split = current_replacement.split("]")
1364
+
1365
+ location_of_current_identifer = find_all_matching_indices(input_file_as_string,current_identifier)
1366
+
1367
+ current_identifier_matches = []
1368
+
1369
+ current_replacement_strings = []
1370
+
1371
+ for y in 0...location_of_current_identifer.length
1372
+
1373
+ current_location = location_of_current_identifer[y]
1374
+
1375
+ extract_string = input_file_as_string[current_location..-1]
1376
+
1377
+ url_extract = extract_string.split(" ",2)
1378
+
1379
+ current_identifier_matches << url_extract[0]
1380
+
1381
+ replacement_string = current_replacement_split[0] + (y+1).to_s + "]"
1382
+
1383
+ current_replacement_strings << replacement_string
1384
+
1385
+ modified_input_string = modified_input_string.sub(url_extract[0],replacement_string)
1386
+
1387
+ end
1388
+
1389
+ identifier_matches << current_identifier_matches
1390
+
1391
+ replacement_strings << current_replacement_strings
1392
+
1393
+ end
1394
+
1395
+ for x in 0...identifier_matches.length
1396
+
1397
+ current_identifer_match = identifier_matches[x]
1398
+
1399
+ replacement_string_array = replacement_strings[x]
1400
+
1401
+ for y in 0...current_identifer_match.length
1402
+
1403
+ urls = current_identifer_match[y]
1404
+
1405
+ interim_replacement = replacement_string_array[y]
1406
+
1407
+ replacement_urls = modify_urls(urls)
1408
+
1409
+ modified_input_string = modified_input_string.sub(interim_replacement,replacement_urls)
1410
+
1411
+
1412
+ end
1413
+
1414
+
1415
+ end
1416
+
1417
+ file_id = open(temporary_file, 'w')
1418
+
1419
+ file_id.write(modified_input_string)
1420
+
1421
+ file_id.close()
1422
+
1423
+ line_by_line_contents = read_file_line_by_line(temporary_file)
1424
+
1425
+ return line_by_line_contents, temporary_file
1426
+
1427
+ end
1428
+
1429
+ def replace_descriptive_urls(input_file_contents,temporary_file)
1430
+
1431
+ def find_all_matching_indices(input_string,pattern)
1432
+
1433
+ locations = []
1434
+
1435
+ index = input_string.index(pattern)
1436
+
1437
+ while index != nil
1438
+
1439
+ locations << index
1440
+
1441
+ index = input_string.index(pattern,index+1)
1442
+
1443
+
1444
+ end
1445
+
1446
+ return locations
1447
+
1448
+
1449
+ end
1450
+
1451
+ def process_urls(input_string)
1452
+
1453
+ core_string = input_string[2...-1]
1454
+
1455
+ split_string = core_string.split("=>")
1456
+
1457
+ return "\\href{#{split_string[1].strip}}{#{split_string[0].strip}}"
1458
+
1459
+ end
1460
+
1461
+ input_file_as_string = input_file_contents.join
1462
+
1463
+ modified_input_string = input_file_as_string.dup
1464
+
1465
+ descriptive_url_locations = find_all_matching_indices(input_file_as_string,"*[")
1466
+
1467
+ replacement_string = "@@descript[]"
1468
+
1469
+ replacement_urls = []
1470
+
1471
+ replacement_strings = []
1472
+
1473
+ for x in 0...descriptive_url_locations.length
1474
+
1475
+ current_location = descriptive_url_locations[x]
1476
+
1477
+ extract_string = input_file_as_string[current_location..-1]
1478
+
1479
+ end_finder = extract_string.index("]")
1480
+
1481
+ descriptive_url = extract_string[0..end_finder]
1482
+
1483
+ replacement_url = process_urls(descriptive_url)
1484
+
1485
+ replacement_urls << replacement_url
1486
+
1487
+ current_replacement_string = replacement_string.sub("]","#{x+1}]")
1488
+
1489
+ replacement_strings << current_replacement_string
1490
+
1491
+ modified_input_string = modified_input_string.sub(descriptive_url,current_replacement_string)
1492
+
1493
+ end
1494
+
1495
+ to_be_replaced = [replacement_strings,replacement_urls]
1496
+
1497
+ file_id = open(temporary_file, 'w')
1498
+
1499
+ file_id.write(modified_input_string)
1500
+
1501
+ file_id.close()
1502
+
1503
+ line_by_line_contents = read_file_line_by_line(temporary_file)
1504
+
1505
+ return line_by_line_contents, temporary_file, to_be_replaced
1506
+
1507
+ end
1508
+
1509
+ def resolve_descriptive_urls(input_file_contents,temporary_file,replacement_array)
1510
+
1511
+ input_file_as_string = input_file_contents.join
1512
+
1513
+ modified_input_string = input_file_as_string.dup
1514
+
1515
+ interim_strings = replacement_array[0]
1516
+
1517
+ descriptive_urls = replacement_array[1]
1518
+
1519
+ for x in 0...interim_strings.length
1520
+
1521
+ current_interim_string = interim_strings[x]
1522
+
1523
+ current_descriptive_url = descriptive_urls[x]
1524
+
1525
+ modified_input_string = modified_input_string.sub(current_interim_string,current_descriptive_url)
1526
+
1527
+ end
1528
+
1529
+ file_id = open(temporary_file, 'w')
1530
+
1531
+ file_id.write(modified_input_string)
1532
+
1533
+ file_id.close()
1534
+
1535
+ line_by_line_contents = read_file_line_by_line(temporary_file)
1536
+
1537
+ return line_by_line_contents, temporary_file
1538
+
1539
+ end
1540
+
1541
+ #The following methods implements some features of Smarty Pants
1542
+
1543
+ #http://daringfireball.net/projects/smartypants/
1544
+
1545
+
1546
+ def resolve_double_quotes(input_file_contents,temporary_file)
1547
+
1548
+ #This feature implements the double quotes features in smarty pants
1549
+
1550
+ def find_all_matching_indices(input_string,pattern)
1551
+
1552
+ locations = []
1553
+
1554
+ index = input_string.index(pattern)
1555
+
1556
+ while index != nil
1557
+
1558
+ locations << index
1559
+
1560
+ index = input_string.index(pattern,index+1)
1561
+
1562
+
1563
+ end
1564
+
1565
+ return locations
1566
+
1567
+
1568
+ end
1569
+
1570
+ input_file_as_string = input_file_contents.join
1571
+
1572
+ modified_input_string = input_file_as_string.dup
1573
+
1574
+ opening_quotes_locations = find_all_matching_indices(input_file_as_string,"\"")
1575
+
1576
+ if opening_quotes_locations.length.modulo(2) == 0
1577
+
1578
+ for x in 0...(opening_quotes_locations.length)/2
1579
+
1580
+ modified_input_string = modified_input_string.sub("\"","``")
1581
+
1582
+ modified_input_string = modified_input_string.sub("\"","''")
1583
+
1584
+ end
1585
+
1586
+ end
1587
+
1588
+ file_id = open(temporary_file, 'w')
1589
+
1590
+ file_id.write(modified_input_string)
1591
+
1592
+ file_id.close()
1593
+
1594
+ line_by_line_contents = read_file_line_by_line(temporary_file)
1595
+
1596
+ return line_by_line_contents, temporary_file
1597
+
1598
+ end
1599
+
1600
+ def convert_to_latex_commands(input_file_contents,temporary_file)
1601
+
1602
+ #This method is designed to be more general than just the features available in smarty pants
1603
+
1604
+ #This method currently implements ellipses
1605
+
1606
+ vanilla_commands = ["...."]
1607
+
1608
+ latex_commands = {"...." => "\\ldots"}
1609
+
1610
+ input_file_as_string = input_file_contents.join
1611
+
1612
+ modified_input_string = input_file_as_string.dup
1613
+
1614
+ vanilla_commands.each do |command|
1615
+
1616
+ modified_input_string = modified_input_string.gsub(command,latex_commands[command])
1617
+
1618
+ end
1619
+
1620
+ file_id = open(temporary_file, 'w')
1621
+
1622
+ file_id.write(modified_input_string)
1623
+
1624
+ file_id.close()
1625
+
1626
+ line_by_line_contents = read_file_line_by_line(temporary_file)
1627
+
1628
+ return line_by_line_contents, temporary_file
1629
+
1630
+ end
1631
+
1632
+ #The following methods are for writing the output LaTex code.
1633
+
1634
+ def write_latex_file(input_file_contents,temporary_file,input_val_file)
1635
+
1636
+ input_file_as_string = input_file_contents.join
1637
+
1638
+ File.delete(temporary_file)
1639
+
1640
+ output_latex_file_path = input_val_file.split(".tex")
1641
+
1642
+ output_latex_file_path = output_latex_file_path[0] + ".tex"
1643
+
1644
+ file_id = open(output_latex_file_path, 'w')
1645
+
1646
+ file_id.write(input_file_as_string)
1647
+
1648
+ file_id.close()
1649
+
1650
+ end
1651
+
1652
+ #The following method compiles the output .tex file into PDF and then overwrites the .tex file with the
1653
+ #original content
1654
+
1655
+ def compile_to_pdf(input_file_path,raw_file_as_string)
1656
+
1657
+ #The method first compiles the .tex file into PDF using PDFLatex
1658
+
1659
+ latex_compiler_output = `pdflatex -interaction=nonstopmode #{input_file_path}`
1660
+
1661
+ file_id = open(input_file_path,'w')
1662
+
1663
+ file_id.write(raw_file_as_string)
1664
+
1665
+ file_id.close()
1666
+
1667
+ return latex_compiler_output
1668
+
1669
+ end
1670
+
1671
+
1672
+ #The following methods are used only for testing and debugging purposes
1673
+
1674
+
1675
+ def print_list(input_list)
1676
+
1677
+ #This method will print each line of the inputted list. This method is usually used to test and see whether other parts of
1678
+ #the compiler are working correctly
1679
+
1680
+ length_of_list = input_list.length
1681
+
1682
+ for x in 0...length_of_list
1683
+
1684
+ current_item = input_list[x]
1685
+
1686
+ print(current_item)
1687
+
1688
+ end
1689
+
1690
+ end
1691
+
1692
+
1693
+ line_by_line_file = read_file_line_by_line(input_val_file)
1694
+
1695
+ raw_file = line_by_line_file.dup
1696
+
1697
+ line_by_line_file, temp_file, fenced_code_blocks, preferred_directory = replace_fenced_code_block(line_by_line_file,input_val_file)
1698
+
1699
+ line_by_line_file, temp_file, inline_code_blocks = replace_inline_fenced_code(line_by_line_file,temp_file)
1700
+
1701
+ line_by_line_file, temp_file = resolve_comments(line_by_line_file,temp_file)
1702
+
1703
+ line_by_line_file, temp_file = resolve_constants(line_by_line_file, temp_file)
1704
+
1705
+ line_by_line_file, temp_file = resolve_formatted_text_blocks(line_by_line_file,temp_file)
1706
+
1707
+ line_by_line_file, temp_file = resolve_formulas(line_by_line_file,temp_file)
1708
+
1709
+ line_by_line_file, temp_file = resolve_inline_calculations(line_by_line_file,temp_file)
1710
+
1711
+ line_by_line_file, temp_file = resolve_inline_formatting(line_by_line_file,temp_file)
1712
+
1713
+ line_by_line_file, temp_file = resolve_tex_packs(line_by_line_file,temp_file,preferred_directory)
1714
+
1715
+ line_by_line_file, temp_file, replacement_array = replace_descriptive_urls(line_by_line_file,temp_file)
1716
+
1717
+ line_by_line_file, temp_file = resolve_bare_urls(line_by_line_file,temp_file)
1718
+
1719
+ line_by_line_file, temp_file = resolve_descriptive_urls(line_by_line_file,temp_file,replacement_array)
1720
+
1721
+ line_by_line_file, temp_file = resolve_double_quotes(line_by_line_file,temp_file)
1722
+
1723
+ line_by_line_file, temp_file = convert_to_latex_commands(line_by_line_file,temp_file)
1724
+
1725
+ line_by_line_file, temp_file = resolve_fenced_code_blocks(line_by_line_file,temp_file,fenced_code_blocks)
1726
+
1727
+ line_by_line_file, temp_file = resolve_inline_fenced_code(line_by_line_file,temp_file,inline_code_blocks)
1728
+
1729
+ write_latex_file(line_by_line_file,temp_file,input_val_file)
1730
+
1731
+ pdflatex_output = compile_to_pdf(input_val_file,raw_file.join)
1732
+
1733
+ return pdflatex_output
1734
+
1735
+ end
1736
+
1737
+ #This script creates a windows executable using the Ocra gem and a mac
1738
+ #version using shabang syntax.
1739
+
1740
+ def create_executable(input_file)
1741
+
1742
+ def read_file_line_by_line(input_path)
1743
+
1744
+ file_id = open(input_path)
1745
+
1746
+ file_line_by_line = file_id.readlines()
1747
+
1748
+ file_id.close
1749
+
1750
+ return file_line_by_line
1751
+
1752
+ end
1753
+
1754
+ windows_output = `ocra --add-all-core #{input_file}`
1755
+
1756
+ mac_file_contents = ["#!/usr/bin/env ruby\n\n"] + read_file_line_by_line(input_file)
1757
+
1758
+ mac_file_path = input_file.sub(".rb","")
1759
+
1760
+ file_id = open(mac_file_path,"w")
1761
+
1762
+ file_id.write(mac_file_contents.join)
1763
+
1764
+ file_id.close
1765
+
1766
+ end
1767
+
1768
+ def create_mac_executable(input_file)
1769
+
1770
+ def read_file_line_by_line(input_path)
1771
+
1772
+ file_id = open(input_path)
1773
+
1774
+ file_line_by_line = file_id.readlines()
1775
+
1776
+ file_id.close
1777
+
1778
+ return file_line_by_line
1779
+
1780
+ end
1781
+
1782
+ mac_file_contents = ["#!/usr/bin/env ruby\n\n"] + read_file_line_by_line(input_file)
1783
+
1784
+ mac_file_path = input_file.sub(".rb", "")
1785
+
1786
+ file_id = open(mac_file_path, "w")
1787
+
1788
+ file_id.write(mac_file_contents.join)
1789
+
1790
+ file_id.close
1791
+
1792
+ end
1793
+
1794
+ options = {}
1795
+
1796
+ OptionParser.new do |opts|
1797
+ opts.banner = "Usage: vanilla [options] TEX_FILE"
1798
+
1799
+ opts.on("-c", "--compile FILE", "Compile to PDF") do |file|
1800
+ current_directory = Dir.pwd
1801
+ file_path = current_directory + "/" + file
1802
+ latex_compiler_output = start_compile(file_path)
1803
+ puts latex_compiler_output
1804
+
1805
+ end
1806
+
1807
+ opts.on("-b", "--build FILE", "Builds Itself") do |file|
1808
+
1809
+ file_path = Dir.pwd + "/src/vanilla.rb"
1810
+
1811
+ create_mac_executable(file_path)
1812
+
1813
+ FileUtils.mv("#{file_path[0...-3]}", "#{Dir.pwd}/bin/vanilla")
1814
+
1815
+ puts "Build Successful!"
1816
+
1817
+ end
1818
+
1819
+ end.parse!