Skip to content

Instantly share code, notes, and snippets.

@AlphaHot
Created September 10, 2024 08:41
Show Gist options
  • Save AlphaHot/eee7ddb8a340f22bde20ee2e76cbe912 to your computer and use it in GitHub Desktop.
Save AlphaHot/eee7ddb8a340f22bde20ee2e76cbe912 to your computer and use it in GitHub Desktop.
//go:build ignore
package main
import (
"fmt"
"html"
"io/ioutil"
"log"
"mime"
"net/http"
"os"
"path/filepath"
"strings"
)
func main() {
// Check if a directory path is provided as a command-line argument
if len(os.Args) < 2 {
log.Fatalf("Usage: %s <directory>", os.Args[0])
}
dir := os.Args[1]
// Check if the directory exists
if _, err := os.Stat(dir); os.IsNotExist(err) {
log.Fatalf("Directory %s does not exist", dir)
}
// Handle file requests
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
// List files in the directory
files, err := ioutil.ReadDir(dir)
if err != nil {
http.Error(w, "Unable to read directory", http.StatusInternalServerError)
return
}
fmt.Fprintln(w, "<h1>Files</h1><ul>")
for _, file := range files {
if !file.IsDir() {
fmt.Fprintf(w, "<li><a href=\"/%s\">%s</a></li>", file.Name(), file.Name())
}
}
fmt.Fprintln(w, "</ul>")
return
}
// Serve the requested file
filePath := filepath.Join(dir, r.URL.Path[1:])
serveFile(w, filePath)
})
// Specify the port to listen on
port := ":8080"
log.Printf("Serving files from %s on http://localhost%s\n", dir, port)
// Start the server
if err := http.ListenAndServe(port, nil); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
func isValidExtension(ext string) bool {
switch ext {
case ".todo", ".mod", ".dot", "go2":
return true
default:
return false
}
}
func serveFile(w http.ResponseWriter, filePath string) {
content, err := ioutil.ReadFile(filePath)
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
return
}
// Determine the content type
ext := filepath.Ext(filePath)
contentType := mime.TypeByExtension(ext)
if isValidExtension(ext) {
contentType = "text/plain" // Force .todo files to be served as text
} else if contentType == "" {
contentType = "application/octet-stream" // Default to binary if unknown
}
// If the file is a text file, display it with line numbers
if strings.HasPrefix(contentType, "text/") {
lineNumberedContent := formatWithLineNumbers(html.EscapeString(string(content)))
w.Header().Set("Content-Type", "text/html")
fmt.Fprintln(w, "<html>")
fmt.Fprintln(w, `<style>
body {
background-color: #000; /* Black background */
color: #00ff00; /* Green text */
}
</style>`)
fmt.Fprintln(w, "<body><pre>")
fmt.Fprintln(w, lineNumberedContent)
fmt.Fprintln(w, "</pre></body></html>")
} else {
// Serve binary files (images, etc.) directly
w.Header().Set("Content-Type", contentType)
w.Write(content)
}
}
func formatWithLineNumbers(content string) string {
lines := strings.Split(content, "\n")
var result strings.Builder
// Start the ordered list
result.WriteString("<p><ol>\n")
for _, line := range lines {
// Append each line as a list item with line number
result.WriteString(fmt.Sprintf("<li>%s</li>", highlightKeywords(line)))
}
// End the ordered list
result.WriteString("</ol></p>\n")
return result.String()
}
// Function to highlight keywords in the text
func highlightKeywords(text string) string {
// Define keywords
keywords := []string{
"break", "case", "chan", "const", "continue",
"default", "defer", "else", "fallthrough", "for",
"func", "go", "goto", "if", "import",
"interface", "map", "package", "range", "return",
"select", "struct", "switch", "type", "var", "main",
"inint", "nil", "make", "copy",
}
highlight := "<mark>$0</mark>" // Highlighting HTML
var builder strings.Builder
start := 0
// Loop through each keyword
for _, keyword := range keywords {
// Find the index of the keyword in the text
for {
index := strings.Index(text[start:], keyword)
if index == -1 {
break
}
// Append the text before the keyword
builder.WriteString(text[start : start+index])
// Append the highlighted keyword
builder.WriteString(strings.ReplaceAll(highlight, "$0", keyword))
// Move the start index past the keyword
start += index + len(keyword)
}
}
// Append any remaining text after the last keyword
builder.WriteString(text[start:])
return builder.String()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment