Initial bonus 2 implementation
git-svn-id: svn+ssh://atelier.inf.usi.ch/home/bevilj/group-1@153 a672b425-5310-4d7a-af5c-997e18724b81
This commit is contained in:
parent
ffd0f87df5
commit
fa85ea6920
12 changed files with 508 additions and 0 deletions
bonus2
13
bonus2/.svnignore
Normal file
13
bonus2/.svnignore
Normal file
|
@ -0,0 +1,13 @@
|
|||
*.iml
|
||||
.idea
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
/lib
|
||||
*.jar
|
||||
/dist
|
||||
|
13
bonus2/bonus2.iml
Normal file
13
bonus2/bonus2.iml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id="bonus2" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/out" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
55
bonus2/build.gradle
Normal file
55
bonus2/build.gradle
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2018. Bevilacqua Joey
|
||||
*/
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.0'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.0'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
apply plugin: 'application'
|
||||
|
||||
defaultTasks 'run'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'org.jsoup:jsoup:1.11.3'
|
||||
}
|
||||
|
||||
mainClassName = 'ch.usi.inf.atelier.group1.Main'
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src'
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
from 'src'
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes 'Main-Class': 'ch.usi.inf.atelier.group1.MainKt'
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
baseName = 'bonus2'
|
||||
classifier = null
|
||||
version = null
|
||||
}
|
59
bonus2/res/test.html
Normal file
59
bonus2/res/test.html
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
layout: page
|
||||
category-title: Basic commands
|
||||
category-page: basic
|
||||
tags: directory change navigate
|
||||
author: Alessandro Marinelli
|
||||
title: cd
|
||||
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>
|
||||
|
||||
The default cd command syntax is:
|
||||
|
||||
<pre>
|
||||
cd [flags] [path]
|
||||
</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>.
|
||||
|
||||
|
||||
<h1>Header 1</h1>
|
||||
|
||||
<h2>Header 2</h2>
|
||||
|
||||
<h4>Header 4</h4>
|
||||
|
||||
<ul>
|
||||
<li>A</li>
|
||||
<li>B: Hello there</li>
|
||||
<li>C</li>
|
||||
<li>D</li>
|
||||
</ul>
|
||||
|
||||
</p>
|
17
bonus2/src/ch/usi/inf/atelier/group1/Main.kt
Normal file
17
bonus2/src/ch/usi/inf/atelier/group1/Main.kt
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2018. Bevilacqua Joey
|
||||
*/
|
||||
package ch.usi.inf.atelier.group1
|
||||
|
||||
import ch.usi.inf.atelier.group1.html.HtmlParser
|
||||
|
||||
object Main {
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
for (arg in args) {
|
||||
println(HtmlParser(arg).parse())
|
||||
}
|
||||
}
|
||||
}
|
83
bonus2/src/ch/usi/inf/atelier/group1/html/HtmlParser.kt
Normal file
83
bonus2/src/ch/usi/inf/atelier/group1/html/HtmlParser.kt
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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"
|
||||
}
|
||||
}
|
55
bonus2/src/ch/usi/inf/atelier/group1/html/JekyllHtmlFile.kt
Normal file
55
bonus2/src/ch/usi/inf/atelier/group1/html/JekyllHtmlFile.kt
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2018. Bevilacqua Joey
|
||||
*/
|
||||
package ch.usi.inf.atelier.group1.html
|
||||
|
||||
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) {
|
||||
val header = HashMap<String, String>()
|
||||
val content: String
|
||||
|
||||
init {
|
||||
val fileContent = file.getContent()
|
||||
val contentBuilder = StringBuilder()
|
||||
|
||||
var isIteratingInHeader = false
|
||||
var line: String? = ""
|
||||
|
||||
val reader = BufferedReader(StringReader(fileContent))
|
||||
|
||||
while (line != null) {
|
||||
if (!isIteratingInHeader && HEADER_START == line) {
|
||||
isIteratingInHeader = true
|
||||
} else if (isIteratingInHeader) {
|
||||
isIteratingInHeader = HEADER_END != line
|
||||
|
||||
if (isIteratingInHeader) {
|
||||
val values = line.split(":")
|
||||
if (values.size == 2) {
|
||||
header[values[0]] = values[1].trim()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
contentBuilder.append(line).append('\n')
|
||||
}
|
||||
|
||||
line = reader.readLine()
|
||||
}
|
||||
|
||||
content = contentBuilder.toString()
|
||||
}
|
||||
|
||||
fun isValid() = header.isNotEmpty() && content.isNotBlank()
|
||||
|
||||
override fun toString() =
|
||||
"Header:\n$header\nContent:\n$content"
|
||||
|
||||
companion object {
|
||||
private const val HEADER_START = "---"
|
||||
private const val HEADER_END = "---"
|
||||
}
|
||||
}
|
128
bonus2/src/ch/usi/inf/atelier/group1/tex/TexDocument.kt
Normal file
128
bonus2/src/ch/usi/inf/atelier/group1/tex/TexDocument.kt
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
}
|
||||
}
|
21
bonus2/src/ch/usi/inf/atelier/group1/util/Log.kt
Normal file
21
bonus2/src/ch/usi/inf/atelier/group1/util/Log.kt
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2018. Bevilacqua Joey
|
||||
*/
|
||||
package ch.usi.inf.atelier.group1.util
|
||||
|
||||
import java.lang.Exception
|
||||
|
||||
object Log {
|
||||
|
||||
fun e(message: String = "", exception: Exception) {
|
||||
e("$message: ${exception.message ?: "Unknown error"}")
|
||||
}
|
||||
|
||||
fun e(message: String) {
|
||||
System.err.println(message)
|
||||
}
|
||||
|
||||
fun i(obj: Any) {
|
||||
println(obj.toString())
|
||||
}
|
||||
}
|
28
bonus2/src/ch/usi/inf/atelier/group1/util/extensions/File.kt
Normal file
28
bonus2/src/ch/usi/inf/atelier/group1/util/extensions/File.kt
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2018. Bevilacqua Joey
|
||||
*/
|
||||
package ch.usi.inf.atelier.group1.util.extensions
|
||||
|
||||
import ch.usi.inf.atelier.group1.util.Log
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.IOException
|
||||
|
||||
fun File.getContent(): String {
|
||||
val content = StringBuilder()
|
||||
try {
|
||||
val reader = BufferedReader(FileReader(this))
|
||||
var line: String? = ""
|
||||
|
||||
while (line != null) {
|
||||
content.append(line)
|
||||
.append('\n')
|
||||
line = reader.readLine()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.e(exception = e)
|
||||
}
|
||||
|
||||
return content.toString()
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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)}"
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
fun TexDocument.writeJekyllHeader(file: JekyllHtmlFile) {
|
||||
val title = file.header["title"] ?: "Unknown title"
|
||||
val author = file.header["author"] ?: "Unknown author"
|
||||
|
||||
setTitle(title)
|
||||
setAuthor(author)
|
||||
}
|
Loading…
Reference in a new issue