bonus2: complete bonus 2

git-svn-id: svn+ssh://atelier.inf.usi.ch/home/bevilj/group-1@167 a672b425-5310-4d7a-af5c-997e18724b81
This commit is contained in:
bevilj 2018-11-13 22:16:49 +00:00
parent 06f9d2b974
commit 4b9169460b
18 changed files with 806 additions and 304 deletions

View File

@ -1,13 +1,13 @@
*.iml
.idea
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
local.properties
.idea/workspace.xml
.idea/libraries
.DS_Store
/build
/captures
/lib
build
captures
lib
*.jar
/dist
dist
res

65
bonus2/ReadMe.md Normal file
View File

@ -0,0 +1,65 @@
# Bonus 2
Author: Bevilacqua Joey
Language: Kotlin
## Build
To compile this exercise `gradle` and `java-1.8` are needed.
To create a working jar executable, run
```
./gradlew shadowJar
```
The output jar will be available at this path: `build/libs/bonus2.jar`
## Execute
```
java -jar bonus2.jar [file1.html] [file2.html] [directory]
```
Both files and directories can be passed as parameter, even at the same.
If a directory is passed as parameter, the program will attemp to
recursively search for Jekyll html files.
The converted LaTeX files will be created in the `out` directory with
subdirectories matching the absolute path of the files passed as argument.
Note that the program will not work with plain html files,
it requires Jekyll html files instead.
A test file is available for reference under the directory `res`.
## Supported tags
### HTML tags
* b -> textbf
* br -> \\
* code -> texttt
* i -> emph
* a -> emph footnote url
* ul -> itemize
* ol -> itemize
* li -> item
* pre -> verbatim
* h1 -> section
* h2 -> subsection
* h3 -> subsubsection
* h4 -> plainText
* h5 -> plainText
* p -> plainText
* table -> table tabular
* u -> underline
### Extra
* comments are removed
* jekyll author -> LaTeX author
* jekyll title -> LaTeX title

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
* Copyright (c) 2018 Bevilacqua Joey.
*/
buildscript {

BIN
bonus2/gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,9 @@
#
# Copyright (c) 2018 Bevilacqua Joey.
#
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

172
bonus2/gradlew vendored Executable file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
bonus2/gradlew.bat vendored Normal file
View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,59 +1,77 @@
---
layout: page
category-title: Basic commands
category-title: Knowledge
category-page: basic
tags: directory change navigate
author: Alessandro Marinelli
title: cd
tags: tragedy know
author: Sheev Palpatine
title: The Tragedy
previous-page: pages/cmd/basic/open.html
next-page: pages/cmd/basic/ls.html
---
<!--
Copyright (c) 2018. Bevilacqua Joey
-->
<p>
The <code>cd</code> command is used to change the working directory<br>
The name stands for <i>Change Directory</i>.<br>
Did you ever hear the tragedy of <b>Darth Plagueis</b> <i>The Wise</i>?<br>
<code>I thought not</code>. Its not a story the Jedi would tell you.</br>
Its a Sith legend. Darth Plagueis was a Dark Lord of the Sith,
so powerful and so wise he could use the Force to influence the midichlorians to <u>create life…</u><br>
He had such a knowledge of the dark side that he could even keep the ones he cared about from dying.<br>
The dark side of the Force is a pathway to many abilities some consider to be unnatural.<br>
He became so powerful… the only thing he was afraid of was losing his power, which eventually, of course, he did.<br>
Unfortunately, he taught his apprentice everything he knew, then his apprentice killed him in his sleep.<br>
<b>Ironic</b>. He could save others from death, but not himself.<br>
The default cd command syntax is:
<h1>Surprise</h1>
<pre>
cd [flags] [path]
A surprise to be sure,
but a welcome one.
</pre>
Where [flags] are the cd flags, read below for more info,and [path] is the
path (absolute or relative), of the directory which we want to make as working directory.<br><br>
<h3>Change the working directory</h3>
Let's see how to use the command <code>cd</code> in order to change the working directory
<pre>
pwd
~
cd Desktop/multimedia
pwd
~/Desktop/multimedia
</pre>
As you can see, we changed the working directory from ~ (which stands for HOME),
to "multimedia". Now our Shell will work on the directory "multimedia"
until a new cd will occour.<br>
<b>Notice:</b> If you want to move to a directory which is not contained in the
current working directory, you <u>MUST</u> use the <a href="foo.html">absolute path</a>.
<table>
<tr>
<td>Take a</td>
<td><b>seat</b></td>
</tr>
<tr>
<td><a href="https://google.com">This</a> is where</td>
<td>The fun begins</td>
</tr>
</table>
<h1>Header 1</h1>
<h3>Fish</h3>
<h2>Header 2</h2>
<h2>Fish</h2>
<h4>Header 4</h4>
<h1>Fish</h1>
There's always bigger fish<br>
[visible confusion]
<ul>
<li>A</li>
<li>B: Hello there</li>
<li>C</li>
<li>D</li>
<li><u>Hello there</u></li>
<li>General Kenobi</li>
<li>You're a <b>bold</b> one</li>
</ul>
<table>
<tr>
<th>The</th>
<th>negotiations</th>
</tr>
<tr>
<td>where</td>
<td>short</td>
</tr>
<tr>
<td>I'll try</td>
<td><i>spinning</i></td>
</tr>
<tr>
<td>that's a</td>
<td>good trick</td>
</tr>
</table>
</p>

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2018 Bevilacqua Joey.
*/
package ch.usi.inf.atelier.group1
import ch.usi.inf.atelier.group1.jekyll.HtmlToLatexWriter
import ch.usi.inf.atelier.group1.jekyll.JekyllPage
import ch.usi.inf.atelier.group1.util.Log
import ch.usi.inf.atelier.group1.util.extensions.insertJekyllHeader
import ch.usi.inf.atelier.group1.util.extensions.writeTo
import java.io.File
class HtmlParser(private val input: File) {
private val file = JekyllPage(input)
private val output = HtmlToLatexWriter(file.content)
fun parse(): String {
if (!file.isValid()) {
Log.e(IllegalArgumentException("This file is not valid"))
}
/*
if (file.header["author"] == "Marwan Announ") {
throw IllegalStateException("Invalid fuckery. Please don\'t attemp to parse this shit. Kthxbye")
}
*/
output.run {
start()
insertJekyllHeader(file)
beginDocument()
changeBold()
changeBr()
changeCode()
changeItalics()
changeLink()
changeList()
changeListItem()
changeMono()
changeParagraph()
changeSection()
changeSubSection()
changeSubSubSection()
changeTable()
changeUnderline()
stripComments()
endDocument()
writeTo(input.absolutePath.replace(".html", ".tex"))
}
return output.toString()
}
}

View File

@ -1,17 +1,34 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
* Copyright (c) 2018 Bevilacqua Joey.
*/
package ch.usi.inf.atelier.group1
import ch.usi.inf.atelier.group1.html.HtmlParser
import java.io.File
object Main {
@JvmStatic
fun main(args: Array<String>) {
for (arg in args) {
println(HtmlParser(arg).parse())
args.forEach(this::convert)
}
/**
* Convert html files to LaTex files
*
* @param path of the file (or directory containing files) to be converted
*/
private fun convert(path: String) {
val file = File(path)
if (!file.isDirectory) {
HtmlParser(file).parse()
return
}
// Recursively search for other html files inside a directory
file.listFiles().filter { it.name.endsWith(".html") || it.isDirectory }
.map { it.path }
.forEach(this::convert)
}
}

View File

@ -1,83 +0,0 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
*/
package ch.usi.inf.atelier.group1.html
import ch.usi.inf.atelier.group1.tex.TexDocument
import ch.usi.inf.atelier.group1.util.Log
import ch.usi.inf.atelier.group1.util.extensions.writeJekyllHeader
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import java.io.File
class HtmlParser(path: String) {
private val file = JekyllHtmlFile(File(path))
private val document = Jsoup.parse(file.content)
private val texDocument = TexDocument()
fun parse(): String {
if (!file.isValid()) {
return ""
}
texDocument.start()
texDocument.writeJekyllHeader(file)
texDocument.beginDocument()
document.body().children().forEach { element -> parseToTex(element) }
texDocument.endDocument()
return texDocument.toString()
}
private fun parseToTex(element: Element) {
val text = element.ownText()
// TODO: fix span elements inside the paragraph senteces (tag-less items)
texDocument.apply {
when (element.tagName()) {
TAG_BOLD -> addBold(text)
TAG_BR -> addBr()
TAG_CODE -> addCode(text)
TAG_H1 -> addSection(text)
TAG_H2 -> addSubSection(text)
TAG_H3, TAG_H4 -> addSubSubSection(text)
TAG_ITALICS -> addItalics(text)
TAG_LINK -> addLink(text, element.attr("href"))
TAG_P -> addParagraph(text)
TAG_PRE -> addPre(text)
TAG_UL -> element.parseList()
"", null -> addText(element.text())
}
}
}
private fun Element.parseList() {
texDocument.apply {
beginList()
children().filter { TAG_LI == it.tagName() }
.forEach { e -> addListItem(e.text()) }
endList()
}
}
companion object {
private const val TAG_BOLD = "b"
private const val TAG_BR = "br"
private const val TAG_CODE = "code"
private const val TAG_H1 = "h1"
private const val TAG_H2 = "h2"
private const val TAG_H3 = "h3"
private const val TAG_H4 = "h4"
private const val TAG_ITALICS = "i"
private const val TAG_LI = "li"
private const val TAG_LINK = "a"
private const val TAG_P = "p"
private const val TAG_PRE = "pre"
private const val TAG_UL = "ul"
}
}

View File

@ -0,0 +1,261 @@
/*
* Copyright (c) 2018 Bevilacqua Joey.
*/
package ch.usi.inf.atelier.group1.jekyll
import org.jsoup.Jsoup
import org.jsoup.parser.Parser
import java.util.regex.Pattern
class HtmlToLatexWriter(private var content: String) {
private val document = StringBuilder()
/**
* Prepare the Latex file
* and insert the header
*/
fun start() {
document.clear()
insert(HEADER, afterLine = true)
}
/**
* Begin the document and insert the title
* and table of contents automatically
*/
fun beginDocument() {
insert("\\begin{document}", afterLine = true)
insert("\\maketitle", afterLine = true)
insert("\\tableofcontents\\")
}
/**
* End the document
*/
fun endDocument() {
insert(content)
insert("\\end{document}", afterLine = true)
}
/**
* Insert a bold text in the document
*/
fun changeBold() {
content = content.replaceTag("<b>", "</b>", "\\textbf{", "}")
}
/**
* Replace <br> with a LaTeX newline
*/
fun changeBr() {
content = content.replaceTag("<br>", null, "\\\\", null)
.replaceTag("</br>", null, "\\\\", null)
}
/**
* Replace <code> with LaTeX \texttt
*/
fun changeCode() {
content = content.replaceTag("<code>", "</code>", "\\texttt{", "}")
}
/**
* Replace <i> with LaTeX \emph
*/
fun changeItalics() {
content = content.replaceTag("<i>", "</i>", "\\emph{", "}")
}
/**
* Replace <a> with LaTeX footNote url
*/
fun changeLink() {
val pattern = Pattern.compile("<a href=\"(.*?)\"(.*?)>(.*?)</a>")
val matcher = pattern.matcher(content)
while (matcher.find()) {
val text = matcher.group(3)
val url = matcher.group(1)
content = content.replace(matcher.group(0), LINK.format(url, text))
}
}
/**
* Replace <ul> and <ol> with LaTeX itemize
*/
fun changeList() {
content = content.replaceTag("<ul>", "</ul>", "\\begin{itemize}", "\\end{itemize}")
.replaceTag("<ol>", "</ol>", "\\begin{itemize}", "\\end{itemize}")
}
/**
* Replace <li> with LaTeX itemize item
*/
fun changeListItem() {
content = content.replaceTag("<li>", "</li>", "\\item ", "")
}
/**
* Replace <pre> with LaTeX verbatim
*/
fun changeMono() {
content = content.replaceTag("<pre>", "</pre>", "\\begin{verbatim}", "\\end{verbatim}")
}
/**
* Replace <p>, empty <a>, <h4> and <h5> with LaTeX plain text
*/
fun changeParagraph() {
content = content.replaceTag("<h4>", "</h4>", "", "")
.replaceTag("<h5>", "</h5>", "", "")
.replaceTag("<p>", "</p>", "\n", "")
.replaceTag("<a>", "</a>", "", "")
}
/**
* Replace <h1> with LaTeX \section
*/
fun changeSection() {
content = content.replaceTag("<h1>", "</h1>", "\\section{", "}\n")
}
/**
* Replace <h2> with LaTeX \subsection
*/
fun changeSubSection() {
content = content.replaceTag("<h2>", "</h2>", "\\subsection{", "}\n")
}
/**
* Replace <h3> with LaTeX \subsubsection
*/
fun changeSubSubSection() {
content = content.replaceTag("<h3>", "</h3>", "\\subsubsection{", "}\n")
}
/**
* Replace <table> with LaTex tabular
*/
fun changeTable() {
val pattern = Pattern.compile("(?:<table>((?:.*?\\r?\\n?)*)</table>)+")
val matcher = pattern.matcher(content)
while (matcher.find()) {
val document = Jsoup.parse(matcher.group(0), "", Parser.xmlParser())
val table = document.select("table")[0]
val rows = table.select("tr")
val columnsDump = ArrayList<String>()
var colCount = 0
for (row in rows) {
var columns = row.select("td")
if (columns.isEmpty()) {
// Maybe this is an header
columns = row.select("th")
}
if (colCount == 0) {
colCount = columns.size
}
val dump = StringBuilder()
columns.map { it.wholeText() }.forEach { dump.append("$it &") }
// Replace the last & with a LaTeX newLine
columnsDump.add(dump.removeSuffix("&").append("\\\\\n"))
}
// Build the LaTeX table
val latexTable = StringBuilder().run {
append("\\begin{table}[h]\n\\begin{tabular}{${"l".repeat(colCount)}}\n")
columnsDump.forEach { append(" $it") }
append("\\end{tabular}\n\\end{table}")
toString()
}
content = content.replace(matcher.group(0), latexTable)
}
}
/**
* Replace <ul> with LaTeX \underline
*/
fun changeUnderline() {
content = content.replaceTag("<u>", "</u>", "\\underline{", "}")
}
/**
* Add an author to the document
*
* @param author the text being inserted
*/
fun addAuthor(author: String) {
insert(AUTHOR.format(author), true, true)
}
/**
* Add a title to the document
*
* @param title the text being inserted
*/
fun addTitle(title: String) {
insert(TITLE.format(title), true, true)
}
/**
* Remove the html comments
*/
fun stripComments() {
content = content.replace(Regex("(?s)<!--.*?-->"), "")
}
/**
* Insert content into the document
*
* @param string the content being inserted
* @param preLine whether a newLine char should be inserted before the content
* @param afterLine whether a newLine char should be inserted after the content
*/
private fun insert(string: String, preLine: Boolean = false, afterLine: Boolean = false) {
document.apply {
if (preLine) {
append("\n")
}
append(string)
if (afterLine) {
append("\n")
}
}
}
private fun String.replaceTag(oldOpen: String, oldClose: String?,
newOpen: String, newClose: String?): String {
var replaced = replace(oldOpen, newOpen)
if (oldClose != null && newClose != null) {
replaced = replaced.replace(oldClose, newClose)
}
return replaced
}
private fun CharSequence.append(append: String) = "${toString()}$append"
override fun toString() = document.toString()
companion object {
private const val AUTHOR = "\\author{%1\$s}"
private const val TITLE = "\\title{%1\$s}"
private const val LINK = "\\underline{\\href{%1\$s}{%2\$s}}"
private const val HEADER =
"\\documentclass[hidelinks,12pt,a4paper,numbers=enddot]{scrartcl}\n\n" +
"\\usepackage[margin=2cm]{geometry}\n" +
"\\usepackage{hyperref}"
}
}

View File

@ -1,15 +1,22 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
* Copyright (c) 2018 Bevilacqua Joey.
*/
package ch.usi.inf.atelier.group1.html
package ch.usi.inf.atelier.group1.jekyll
import ch.usi.inf.atelier.group1.util.extensions.getContent
import java.io.BufferedReader
import java.io.File
import java.io.StringReader
class JekyllHtmlFile(file: File) {
class JekyllPage(file: File) {
/**
* The jekyll header variables
*/
val header = HashMap<String, String>()
/**
* The jekyll html code
*/
val content: String
init {
@ -28,12 +35,14 @@ class JekyllHtmlFile(file: File) {
isIteratingInHeader = HEADER_END != line
if (isIteratingInHeader) {
// Import a jekyll variable
val values = line.split(":")
if (values.size == 2) {
header[values[0]] = values[1].trim()
}
}
} else {
// Import html code
contentBuilder.append(line).append('\n')
}
@ -43,10 +52,14 @@ class JekyllHtmlFile(file: File) {
content = contentBuilder.toString()
}
/**
* Check whether the imported file actually had valid content
*
* @return true if the header and the content aren't empty
*/
fun isValid() = header.isNotEmpty() && content.isNotBlank()
override fun toString() =
"Header:\n$header\nContent:\n$content"
override fun toString() = "Header:\n$header\nContent:\n$content"
companion object {
private const val HEADER_START = "---"

View File

@ -1,128 +0,0 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
*/
package ch.usi.inf.atelier.group1.tex
class TexDocument {
private val document = StringBuilder()
fun start() {
document.clear()
insert(HEADER, false, true)
}
fun beginDocument() {
insert("\\begin{document}", false, true)
insert("\\maketitle", false, true)
insert("\\tableofcontents", false, true)
insert("\\newpage", false, true)
}
fun endDocument() {
insert("\\end{document}", false, true)
}
fun addParagraph(content: String) {
if (content.isNotBlank()) {
insert(content, true, true)
}
}
fun addText(content: String) {
if (content.isNotBlank()) {
insert(content, false, true)
}
}
fun addSection(content: String) {
insert(SECTION.format(content, content.trim().toLowerCase()), false, true)
}
fun addSubSection(content: String) {
insert(SUB_SECTION.format(content), false, true)
}
fun addSubSubSection(content: String) {
insert(SUB_SUB_SECTION.format(content), false, true)
}
fun addBold(content: String) {
insert(BOLD.format(content), false, false)
}
fun addItalics(content: String) {
insert(ITALICS.format(content), false, false)
}
fun addCode(content: String) {
insert(CODE.format(content), false, false)
}
fun addPre(content: String) {
insert(PRE.format(content), false, true)
}
fun addLink(content: String, url: String) {
insert(LINK.format(content, url), false, true)
}
fun beginList() {
insert("\\begin{itemize}", false, true)
}
fun endList() {
insert("\\end{itemize}", false, true)
}
fun addListItem(content: String) {
insert(LIST_ITEM.format(content), false, true)
}
fun addBr() {
insert("", false, false)
}
fun setAuthor(content: String) {
insert(AUTHOR.format(content), false, true)
}
fun setTitle(content: String) {
insert(TITLE.format(content), false, true)
}
private fun insert(string: String, newLine: Boolean, endLine: Boolean) {
document.apply {
append(string)
if(newLine) {
append("\\\\")
}
if (endLine) {
append("\n")
}
}
}
override fun toString() = document.toString()
companion object {
private const val AUTHOR = "\\author{%1\$s}\n"
private const val BOLD = "\\textbf{%1\$s}"
private const val CODE = "\\texttt{%1\$s}"
private const val ITALICS = "\\emph{%1\$s}"
private const val LINK = "\\emph{%1\$s} \\footnote{\\url{%2\$s}}"
private const val LIST_ITEM = "\\item %1\$s"
private const val PRE = "\n\\begin{verbatim}\n%1\$s\n\\end{verbatim}"
private const val SECTION = "\\section{%1\$s}\\label{%2\$s}"
private const val SUB_SECTION = "\\subsection{%1\$s}"
private const val SUB_SUB_SECTION = "\\subsubsection{%1\$s}"
private const val TITLE = "\\title{%1\$s}\n"
private const val HEADER =
"\\documentclass[hidelinks,12pt,a4paper,numbers=enddot]{scrartcl}\n\n" +
"\\usepackage[margin=2cm]{geometry}\n" +
"\\usepackage{hyperref}\n"
}
}

View File

@ -1,21 +1,28 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
* Copyright (c) 2018 Bevilacqua Joey.
*/
package ch.usi.inf.atelier.group1.util
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
object Log {
fun e(message: String = "", exception: Exception) {
e("$message: ${exception.message ?: "Unknown error"}")
}
fun e(message: String) {
System.err.println(message)
fun e(exception: Exception) {
print('E', exception.message ?: "Unknown error", true)
}
fun i(obj: Any) {
println(obj.toString())
print('I', obj.toString(), false)
}
private fun print(prefix: Char, message: String, isErr: Boolean) {
val time = SimpleDateFormat("yyyy-MM-dd hh:mm").format(Date())
if (isErr) {
System.err.println("$prefix $time\t$message")
} else {
System.out.println("$prefix $time\t$message")
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
* Copyright (c) 2018 Bevilacqua Joey.
*/
package ch.usi.inf.atelier.group1.util.extensions
@ -9,6 +9,11 @@ import java.io.File
import java.io.FileReader
import java.io.IOException
/**
* Get the content of the file as String
*
* @return this File content
*/
fun File.getContent(): String {
val content = StringBuilder()
try {

View File

@ -1,21 +0,0 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
*/
package ch.usi.inf.atelier.group1.util.extensions
import ch.usi.inf.atelier.group1.util.Log
import java.io.File
import java.io.IOException
fun String.toFile(): File? {
try {
File(this)
} catch (e: IOException) {
Log.e("Failed to open $this as File", e)
throw e
}
return null
}
fun String.getClosingTag() = "</${substring(1, length)}"

View File

@ -1,15 +1,39 @@
/*
* Copyright (c) 2018. Bevilacqua Joey
* Copyright (c) 2018 Bevilacqua Joey.
*/
package ch.usi.inf.atelier.group1.util.extensions
import ch.usi.inf.atelier.group1.html.JekyllHtmlFile
import ch.usi.inf.atelier.group1.tex.TexDocument
import ch.usi.inf.atelier.group1.jekyll.HtmlToLatexWriter
import ch.usi.inf.atelier.group1.jekyll.JekyllPage
import ch.usi.inf.atelier.group1.util.Log
import java.io.File
import java.io.FileWriter
fun TexDocument.writeJekyllHeader(file: JekyllHtmlFile) {
/**
* Insert author and title from Jekyll file
*/
fun HtmlToLatexWriter.insertJekyllHeader(file: JekyllPage) {
val title = file.header["title"] ?: "Unknown title"
val author = file.header["author"] ?: "Unknown author"
setTitle(title)
setAuthor(author)
addTitle(title)
addAuthor(author)
}
fun HtmlToLatexWriter.writeTo(path: String) {
val outDir = File("out", File(path).parent)
if (!outDir.exists()) {
outDir.mkdirs()
}
val file = File("out", path)
val writer = FileWriter(file, false)
Log.i("${file.path} created")
writer.write(toString())
writer.flush()
writer.close()
}