minor changes

This commit is contained in:
Maximilian Wagner
2025-12-27 22:52:04 +01:00
parent b65ed45477
commit 2c05415ed1
7 changed files with 160 additions and 42 deletions

View File

@@ -261,7 +261,6 @@ func LatexCompile() error {
} }
LogLine("LaTeX execution started", 2) LogLine("LaTeX execution started", 2)
execution.ExecutionState = "Started"
var latexCommand *exec.Cmd var latexCommand *exec.Cmd
switch config.LatexEngine { switch config.LatexEngine {
@@ -282,19 +281,17 @@ func LatexCompile() error {
return errors.New("Unsupported LaTeX Engine") return errors.New("Unsupported LaTeX Engine")
} }
execution.ExecutionState = "Running"
stdout, err := latexCommand.Output() stdout, err := latexCommand.Output()
if err != nil {
execution.ExecutionState = "Failed"
return err
}
execution.Output = stdout execution.Output = stdout
execution.ExecutionState = "Done" if err == nil {
execution.ExecutionState = globals.LatexExecutionStateSuccess
} else {
execution.ExecutionState = globals.LatexExecutionStateFailure
}
updateExecutionTimestamp(execution) updateExecutionTimestamp(execution)
LogLine("LaTeX execution finished", 2) LogLine("LaTeX execution finished", 2)
return nil return err
} }
// Checks whether the proxy is trusted. Returns trusted status and the proxy. // Checks whether the proxy is trusted. Returns trusted status and the proxy.

View File

@@ -1,18 +1,20 @@
.output { .output {
height: 80vh; height: 75vh;
} }
.left-sidebar { .left-sidebar {
padding: 15px; padding: 10px;
width: 15vw;
height: 100%; height: 100%;
resize: both;
} }
.pdf-frame { .pdf-frame {
width: 100%; width: 85vw;
height: 100%; height: 100%;
border: none; border: none;
} }
.command-out { .command-out {
height: 20vh; height: 25vh;
padding: 20px; padding: 5px;
background-color: #eaeaea; background-color: #eaeaea;
overflow-y: auto; overflow-y: auto;
} }

View File

@@ -10,29 +10,30 @@
<script src="/jscss/htmx-ext-sse.js"></script> <script src="/jscss/htmx-ext-sse.js"></script>
</head> </head>
<body> <body>
<div class="container-fluid h-100 d-flex flex-column" hx-ext="sse" sse-connect="/sse"> <div class="container-fluid h-100 d-flex flex-column" hx-ext="sse" sse-connect="/sse">
<div class="row output flex-grow-1"> <div class="row output flex-grow-1">
<div class="col-3 left-sidebar d-flex flex-column justify-content-between"> <div class="col-3 left-sidebar d-flex flex-column justify-content-between">
<div> <div>
<h4>ServTeX Status</h4> <br> <h4>ServTeX</h4> <br>
<div sse-swap="status"> <div sse-swap="status">
Compilation has not run yet. Compilation information unavailable.
</div> </div>
</div> </div>
<br> <br>
<button class="btn btn-primary mt-2" hx-post="/compile" hx-trigger="click" hx-swap="none">Recompile</button> <button class="btn btn-primary mt-2" hx-post="/compile" hx-trigger="click" hx-swap="none">Recompile</button>
</div> </div>
<div class="col-9 p-0" sse-swap="pdf"> <div class="col-9 p-0" sse-swap="pdf">
<iframe class="pdf-frame" src="/pdf?ts=0"></iframe> <iframe class="pdf-frame" src="/pdf?ts=0"></iframe>
</div> </div>
</div> </div>
<div class="command-out" sse-swap="output">
</div> <div class="command-out" sse-swap="output"></div>
</div>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -34,8 +34,8 @@ func ssePing(writer *http.ResponseWriter) {
// Reads globals.LatexExec // Reads globals.LatexExec
func sseStatusSend(writer *http.ResponseWriter) { func sseStatusSend(writer *http.ResponseWriter) {
fmt.Fprintf((*writer), "event: status\n") fmt.Fprintf((*writer), "event: status\n")
fmt.Fprintf((*writer), "data: Execution Time: %s<br>\n", globals.LatexExec.Timestamp) fmt.Fprintf((*writer), "data: Execution Time:<br>%s<br><br>\n", globals.LatexExec.Timestamp)
fmt.Fprintf((*writer), "data: Execution State: %s<br>\n\n", globals.LatexExec.ExecutionState) fmt.Fprintf((*writer), "data: Execution State:<br>%s<br>\n\n", globals.LatexExec.ExecutionState)
(*writer).(http.Flusher).Flush() (*writer).(http.Flusher).Flush()
backend.LogLine("Status Event has been sent", 1) backend.LogLine("Status Event has been sent", 1)
@@ -85,24 +85,24 @@ func SSEventHandler(writer http.ResponseWriter, request *http.Request) {
ssePing(&writer) ssePing(&writer)
lastExecution := "" lastExecution := &globals.LatexExecution{}
for range time.Tick(time.Second) { for range time.Tick(time.Second) {
select { select {
case <-request.Context().Done(): case <-request.Context().Done():
return return
default: default:
if lastExecution == globals.LatexExec.TimestampRFC { if lastExecution.Equal(&globals.LatexExec) {
ssePing(&writer) ssePing(&writer)
} else { } else {
sseStatusSend(&writer) sseStatusSend(&writer)
sseOutputSend(&writer) sseOutputSend(&writer)
// let client keep current pdf, if compile failed // let client keep current pdf, if compile failed
if globals.LatexExec.ExecutionState != "Failed" { if globals.LatexExec.ExecutionState != globals.LatexExecutionStateFailure {
ssePDFSend(&writer) ssePDFSend(&writer)
}
lastExecution = globals.LatexExec.TimestampRFC
} }
lastExecution = globals.LatexExec.Copy()
} }
}
} }
} }

View File

@@ -38,6 +38,35 @@ type LatexExecution struct {
Output []byte Output []byte
} }
var LatexExec LatexExecution var LatexExec LatexExecution
var LatexExecutionStateSuccess = "Success"
var LatexExecutionStateFailure = "Failure"
// Creates a copy of a LatexExecution (without the Mutex)
func (execution *LatexExecution) Copy() (exeCopy *LatexExecution) {
if execution == nil { return nil }
exeCopy = &LatexExecution{
ExecutionState: execution.ExecutionState,
Timestamp: execution.Timestamp,
TimestampRFC: execution.TimestampRFC,
}
if execution.Output != nil {
exeCopy.Output = make([]byte, len(execution.Output))
copy(exeCopy.Output, execution.Output)
}
return exeCopy
}
// Returns whether the two executions are equal
func (left *LatexExecution) Equal(right *LatexExecution) (isEqual bool) {
if left.ExecutionState != right.ExecutionState { return false }
if left.Timestamp != right.Timestamp { return false }
if left.TimestampRFC != right.TimestampRFC { return false }
if string(left.Output) != string(right.Output) { return false }
return true
}
type ClientInfo struct { type ClientInfo struct {
ClientIP string ClientIP string

View File

@@ -77,7 +77,7 @@ func main() {
// shutdown // shutdown
// known issue: sse blocks shutdown if a client is still connected // known issue: sse blocks shutdown if a client is still connected
context, cancel := context.WithTimeout(context.Background(), 5*time.Second) context, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() defer cancel()
server.Shutdown(context) server.Shutdown(context)
serverSecure.Shutdown(context) serverSecure.Shutdown(context)

View File

@@ -1,6 +1,95 @@
\documentclass{article} % This Example is AI-generated
\documentclass[12pt]{article}
\usepackage[a4paper,margin=1in]{geometry}
\title{Untitled Collection}
\author{ChatGPT}
\date{27.12.2025}
\begin{document} \begin{document}
(This is an Example Document) \maketitle
Filewatcher Test Document
Filewatcher Test Document \section*{Poem I}
The clock forgets the hour it keeps,\\
Ticks dissolving into air.\\
A window leans against the light,\\
Certain someone once stood there.
Words arrive without a mouth,\\
Footsteps hum inside the floor.\\
Meaning is a temporary guest,\\
Memory, a bolted door.
\bigskip
The sea repeats a single thought,\\
Correcting it with foam.\\
Every wave believes itself\\
The last to find a home.
\section*{Poem II}
Static gathers in the room,\\
Ideas flicker, then persist.\\
A sentence tries to finish itself\\
And fails deliberately mid-
Silence executes a perfect turn,\\
No witnesses remain.\\
The poem folds its syntax up\\
And waits to be explained.
\newpage
\section*{Poem III}
Morning compiles the streets again,\\
Linking shadows, heat, and dust.\\
The sun asserts a theorem\\
No one bothers to distrust.
Coffee cools. The day begins.\\
Assumptions pass as facts.\\
Every plan degrades to noise\\
Once time begins to act.
\section*{Poem IV}
At night the city dereferences\\
Its towers into black.\\
Stars leak through abstraction gaps\\
The daylight failed to patch.
Sleep runs a background process,\\
Dreams spike the CPU.\\
By dawn the system boots once more,\\
Convinced the past was true.
\section*{Poem V}
The map insists the road is straight,\\
Though every mile disagrees.\\
Coordinates drift quietly\\
Between intent and certainty.
A compass spins, then settles down,\\
Pretending it was sure.\\
Direction is a post-hoc claim\\
We annotate as we move.
\section*{Poem VI}
The archive hums with idle truth,\\
Compressed but never gone.\\
Each file recalls a version where\\
The ending carried on.
We label loss as cleanup work,\\
Deletion dressed as care.\\
Nothing vanishes outright—\\
It only changes where.
\end{document} \end{document}