Compare commits
2 Commits
19752a0c89
...
lsp
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b2be7b4e7 | |||
| 99c41a0d60 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1 @@
|
||||
fes
|
||||
*.tar.gz
|
||||
|
||||
8
.luarc.json
Normal file
8
.luarc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"workspace.library": [
|
||||
"./lsp"
|
||||
],
|
||||
"diagnostics.disable": [
|
||||
"undefined-global"
|
||||
]
|
||||
}
|
||||
4
COPYING
4
COPYING
@@ -1,6 +1,6 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2025-2026 fSD
|
||||
Copyright (c) 2025 fSD
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -12,4 +12,4 @@ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
17
Dockerfile
17
Dockerfile
@@ -4,17 +4,24 @@ WORKDIR /src
|
||||
|
||||
RUN apk add --no-cache git build-base
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN make
|
||||
ENV CGO_ENABLED=0
|
||||
ENV GOOS=linux
|
||||
ENV GOARCH=amd64
|
||||
|
||||
FROM alpine:3.19
|
||||
RUN go build -ldflags="-X fes/modules/version.gitCommit=$(git rev-parse --short HEAD) -s -w" -o fes
|
||||
|
||||
COPY --from=builder /src/fes /usr/local/bin/fes
|
||||
FROM scratch
|
||||
|
||||
COPY --from=builder /src/fes /fes
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
EXPOSE 3000
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/fes"]
|
||||
ENTRYPOINT ["/fes"]
|
||||
CMD ["run", "/app"]
|
||||
|
||||
@@ -40,6 +40,6 @@ Run `fes doc` for the documentation website or goto [docs.vxserver.dev](https://
|
||||
|
||||
ISC License
|
||||
|
||||
Copyright (C) 2025-2026 fSD
|
||||
Copyright (C) 2025 fSD
|
||||
|
||||
See `COPYING`
|
||||
|
||||
31
lsp/fes.lua
Normal file
31
lsp/fes.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
---@meta
|
||||
|
||||
---@class Fes
|
||||
---@field version string|nil
|
||||
---@field title string|nil
|
||||
---@field copyright string|nil
|
||||
---@field favicon string|nil
|
||||
---@field header string
|
||||
---@field footer string
|
||||
---@field parts string[]
|
||||
---@field [string] fun(self: Fes, ...: any): Fes
|
||||
|
||||
local Fes = {}
|
||||
Fes.__index = Fes
|
||||
|
||||
---@param header? string
|
||||
---@param footer? string
|
||||
---@return Fes
|
||||
function Fes.fes(header, footer) end
|
||||
|
||||
---@param html string
|
||||
---@return Fes
|
||||
function Fes:custom(html) end
|
||||
|
||||
---@return string
|
||||
function Fes:build() end
|
||||
|
||||
---@return string
|
||||
function Fes:__tostring() end
|
||||
|
||||
return Fes
|
||||
155
lsp/std.lua
Normal file
155
lsp/std.lua
Normal file
@@ -0,0 +1,155 @@
|
||||
---@meta
|
||||
|
||||
---@class FesStd
|
||||
local M = {}
|
||||
|
||||
---@return string
|
||||
function M.fes_version() end
|
||||
|
||||
---@return string
|
||||
function M.site_version() end
|
||||
|
||||
---@param link? string
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.a(link, str) end
|
||||
|
||||
---@param link? string
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.ha(link, str) end
|
||||
|
||||
---@param link string
|
||||
---@param str string
|
||||
---@return string
|
||||
function M.external(link, str) end
|
||||
|
||||
---@param str string
|
||||
---@return string
|
||||
function M.note(str) end
|
||||
|
||||
---@param str string
|
||||
---@return string
|
||||
function M.muted(str) end
|
||||
|
||||
---@param str string
|
||||
---@return string
|
||||
function M.callout(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.h1(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.h2(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.h3(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.h4(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.h5(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.h6(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.p(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.pre(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.code(str) end
|
||||
|
||||
---@param items? any[]
|
||||
---@return string
|
||||
function M.ul(items) end
|
||||
|
||||
---@param items? any[]
|
||||
---@return string
|
||||
function M.ol(items) end
|
||||
|
||||
---@param items? any[]
|
||||
---@return string
|
||||
function M.tl(items) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.blockquote(str) end
|
||||
|
||||
---@return string
|
||||
function M.hr() end
|
||||
|
||||
---@param src? string
|
||||
---@param alt? string
|
||||
---@return string
|
||||
function M.img(src, alt) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.strong(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.em(str) end
|
||||
|
||||
---@return string
|
||||
function M.br() end
|
||||
|
||||
---@param content? string
|
||||
---@param class? string
|
||||
---@return string
|
||||
function M.div(content, class) end
|
||||
|
||||
---@param content? string
|
||||
---@param class? string
|
||||
---@return string
|
||||
function M.span(content, class) end
|
||||
|
||||
---@param str any
|
||||
---@return string
|
||||
function M.escape(str) end
|
||||
|
||||
---@return string
|
||||
function M.site_name() end
|
||||
|
||||
---@return string
|
||||
function M.site_title() end
|
||||
|
||||
---@return any[]
|
||||
function M.site_authors() end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.highlight(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.banner(str) end
|
||||
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.center(str) end
|
||||
|
||||
---@param link? string
|
||||
---@param str? string
|
||||
---@return string
|
||||
function M.nav(link, str) end
|
||||
|
||||
---@param right? string
|
||||
---@param left? string
|
||||
---@return string
|
||||
function M.rl(right, left) end
|
||||
|
||||
return M
|
||||
20
lsp/symbol.lua
Normal file
20
lsp/symbol.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
---@meta
|
||||
|
||||
---@class FesSymbol
|
||||
local M = {}
|
||||
|
||||
|
||||
--@type string
|
||||
--@readonly
|
||||
M.copyright = "©"
|
||||
|
||||
--@type string
|
||||
--@readonly
|
||||
M.registered_trademark = "®"
|
||||
|
||||
--@type string
|
||||
--@readonly
|
||||
M.trademark = "™"
|
||||
|
||||
return M
|
||||
15
lsp/util.lua
Normal file
15
lsp/util.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
---@meta
|
||||
|
||||
---@class CopyrightUtil
|
||||
local M = {}
|
||||
|
||||
---@param tbl string[]
|
||||
---@return string
|
||||
function M.cc(tbl) end
|
||||
|
||||
---@param link string
|
||||
---@param holder string
|
||||
---@return string
|
||||
function M.copyright(link, holder) end
|
||||
|
||||
return M
|
||||
67
main.go
67
main.go
@@ -6,21 +6,23 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/fatih/color"
|
||||
|
||||
"fes/modules/config"
|
||||
"fes/modules/doc"
|
||||
"fes/modules/lsp"
|
||||
"fes/modules/new"
|
||||
"fes/modules/server"
|
||||
"fes/modules/ui"
|
||||
"fes/modules/version"
|
||||
)
|
||||
|
||||
//go:embed lib/*
|
||||
var lib embed.FS
|
||||
|
||||
//go:embed lsp/*
|
||||
var lspStubs embed.FS
|
||||
|
||||
//go:embed index.html
|
||||
var documentation string
|
||||
|
||||
@@ -29,20 +31,20 @@ func init() {
|
||||
config.Color = flag.Bool("no-color", false, "Disable color output")
|
||||
config.Static = flag.Bool("static", false, "Render and save all pages")
|
||||
config.Docker = flag.Bool("docker", false, "Create a docker project")
|
||||
|
||||
config.Lib = lib
|
||||
config.LspStubs = lspStubs
|
||||
config.Doc = documentation
|
||||
config.Verbose = flag.Bool("verbose", false, "Enable verbose logging")
|
||||
}
|
||||
|
||||
func main() {
|
||||
var m runtime.MemStats
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [options] <command> <project_dir>\n", os.Args[0])
|
||||
fmt.Fprintln(flag.CommandLine.Output(), "Commands:")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " new <project_dir> Create a new project")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " doc Open documentation")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " run <project_dir> Start the server")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " lsp <sub_command> Work with Lsp")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), "Options:")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintln(flag.CommandLine.Output(), "For bug reports, contact a developer and describe the issue. Provide the output of the `-V1` flag.")
|
||||
@@ -65,10 +67,6 @@ func main() {
|
||||
color.NoColor = true
|
||||
}
|
||||
|
||||
if *config.Port == 3000 {
|
||||
ui.WARNING("Using default port, this may lead to conflicts with other services")
|
||||
}
|
||||
|
||||
args := flag.Args()
|
||||
if len(args) < 1 {
|
||||
flag.Usage()
|
||||
@@ -76,38 +74,39 @@ func main() {
|
||||
}
|
||||
|
||||
cmd := args[0]
|
||||
var dir string
|
||||
if cmd == "new" || cmd == "run" {
|
||||
if len(args) < 2 {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s requires <project_dir>\n", cmd)
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
dir = args[1]
|
||||
}
|
||||
var arg string
|
||||
|
||||
switch cmd {
|
||||
case "new":
|
||||
if err := new.Project(dir); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
case "doc":
|
||||
if cmd == "doc" {
|
||||
if err := doc.Open(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if len(args) < 2 {
|
||||
fmt.Fprintln(os.Stderr, "Error: not enough arguments")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
arg = args[1]
|
||||
|
||||
switch cmd {
|
||||
case "new":
|
||||
if err := new.Project(arg); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
case "lsp":
|
||||
if err := lsp.Do(arg); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
case "run":
|
||||
ui.Log("Fes is starting")
|
||||
ui.Log("Fes version=%s, commit=%s, just started", version.VERSION, version.GetCommit())
|
||||
|
||||
runtime.ReadMemStats(&m)
|
||||
ui.Log("FRE memory usage when created %v Mb", m.TotalAlloc/1024/1024)
|
||||
|
||||
if err := server.Start(dir); err != nil {
|
||||
if err := server.Start(arg); err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
fmt.Fprintf(os.Stderr, "%s does not exist\n", dir)
|
||||
fmt.Fprintf(os.Stderr, "Try: fes new %s\n", dir)
|
||||
fmt.Fprintf(os.Stderr, "%s does not exist\n", arg)
|
||||
fmt.Fprintf(os.Stderr, "Try: fes new %s\n", arg)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, "Error:", err)
|
||||
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
)
|
||||
|
||||
var Lib embed.FS
|
||||
var LspStubs embed.FS
|
||||
|
||||
var Doc string
|
||||
var Port *int
|
||||
var Color *bool
|
||||
var Static *bool
|
||||
var Docker *bool
|
||||
var Verbose *bool
|
||||
|
||||
type AppConfig struct {
|
||||
App struct {
|
||||
|
||||
173
modules/lsp/lsp.go
Normal file
173
modules/lsp/lsp.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"fes/modules/config"
|
||||
)
|
||||
|
||||
var destRoot string = filepath.Join(func () string {
|
||||
res, err := os.UserHomeDir()
|
||||
if err != nil { panic(err) }
|
||||
return res
|
||||
}(), ".local", "LuaAddons", "fes")
|
||||
|
||||
func usage(status int) {
|
||||
fmt.Fprintln(flag.CommandLine.Output(), "Lsp Usage:")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " help Print this help and exit")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " install Install the Lsp")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " uninstall Uninstall the Lsp")
|
||||
fmt.Fprintln(flag.CommandLine.Output(), " doctor Verify Lsp installation")
|
||||
os.Exit(status)
|
||||
}
|
||||
|
||||
func writeFile(fs embed.FS, src, dst string) error {
|
||||
in, err := fs.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, in)
|
||||
return err
|
||||
}
|
||||
|
||||
func install() error {
|
||||
if err := os.RemoveAll(destRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var found bool
|
||||
|
||||
err := fsWalkDir(config.LspStubs, "lsp", func(path string) error {
|
||||
if path == "lsp" {
|
||||
return nil
|
||||
}
|
||||
|
||||
rel := strings.TrimPrefix(path, "lsp/")
|
||||
dst := filepath.Join("library", destRoot, rel)
|
||||
|
||||
info, err := fsStat(config.LspStubs, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(dst, 0755)
|
||||
}
|
||||
|
||||
found = true
|
||||
return writeFile(config.LspStubs, path, dst)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !found {
|
||||
return errors.New("no lsp stubs found in embedded fs")
|
||||
}
|
||||
|
||||
err = os.WriteFile(filepath.Join("dstRoot", "config.json"), []byte(""), 0755)
|
||||
|
||||
fmt.Println("Lua LSP installed to:", destRoot)
|
||||
return nil
|
||||
}
|
||||
|
||||
func uninstall() error {
|
||||
if _, err := os.Stat(destRoot); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
fmt.Println("Lua LSP not installed")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(destRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Lua LSP uninstalled from:", destRoot)
|
||||
return nil
|
||||
}
|
||||
|
||||
func doctor() error {
|
||||
info, err := os.Stat(destRoot)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errors.New("lsp not installed")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
return errors.New("lsp install path is not a directory")
|
||||
}
|
||||
|
||||
var luaFiles int
|
||||
|
||||
err = filepath.Walk(destRoot, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() && strings.HasSuffix(info.Name(), ".lua") {
|
||||
luaFiles++
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if luaFiles == 0 {
|
||||
return errors.New("no lua stubs found in lsp directory")
|
||||
}
|
||||
|
||||
fmt.Println("LSP stubs: OK")
|
||||
fmt.Println("Location:", destRoot)
|
||||
fmt.Println()
|
||||
fmt.Println("LuaLS configuration required:")
|
||||
fmt.Println()
|
||||
fmt.Println(` "Lua.workspace.library": {`)
|
||||
fmt.Printf(` "%s": true`, destRoot)
|
||||
fmt.Println()
|
||||
fmt.Println(` }`)
|
||||
fmt.Println()
|
||||
fmt.Println("Restart your editor after installing or updating the LSP stubs")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Do(arg string) error {
|
||||
switch arg {
|
||||
case "help":
|
||||
usage(0)
|
||||
case "install":
|
||||
return install()
|
||||
case "uninstall":
|
||||
return uninstall()
|
||||
case "doctor":
|
||||
return doctor()
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Unknown command: %s\n", arg)
|
||||
usage(1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
36
modules/lsp/util.go
Normal file
36
modules/lsp/util.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package lsp
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func fsWalkDir(fs embed.FS, root string, fn func(string) error) error {
|
||||
entries, err := fs.ReadDir(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, e := range entries {
|
||||
p := filepath.Join(root, e.Name())
|
||||
if err := fn(p); err != nil {
|
||||
return err
|
||||
}
|
||||
if e.IsDir() {
|
||||
if err := fsWalkDir(fs, p, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fsStat(fs embed.FS, path string) (os.FileInfo, error) {
|
||||
f, err := fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
return f.Stat()
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package new
|
||||
|
||||
import (
|
||||
"fes/modules/config"
|
||||
"fes/modules/ui"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -115,15 +114,5 @@ All commands are run from the root of the project, from a terminal:
|
||||
## What to learn more?
|
||||
|
||||
Check out [Fes's docs](https://docs.vxserver.dev/static/fes.html).`, "$$", "`"), dir, dir)
|
||||
|
||||
ui.Hint("you can run this with `fes run %s`", dir)
|
||||
|
||||
fmt.Println("Created new Fes project at", func() string {
|
||||
if res, err := filepath.Abs(dir); err == nil {
|
||||
return res
|
||||
}
|
||||
return dir
|
||||
}())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fes/modules/config"
|
||||
"fes/modules/ui"
|
||||
"fmt"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
@@ -14,9 +15,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
)
|
||||
|
||||
/* this is the request data we pass over the bus to the application, via the fes.bus interface */
|
||||
@@ -380,26 +378,18 @@ func loadDirs() map[string]string {
|
||||
|
||||
/* helper to parse the Fes.toml and generate config */
|
||||
func parseConfig() config.AppConfig {
|
||||
defaultCfg := config.AppConfig{}
|
||||
defaultCfg.App.Authors = []string{"unknown"}
|
||||
defaultCfg.App.Name = "unknown"
|
||||
defaultCfg.App.Version = "unknown"
|
||||
|
||||
tomlDocument, err := os.ReadFile("Fes.toml")
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
ui.WARN("no config file found, using the default config. In order to specify a config file write to Fes.toml")
|
||||
return defaultCfg
|
||||
} else {
|
||||
ui.Error("failed to read Fes.toml", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ui.Error("failed to read Fes.toml", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
docStr := fixMalformedToml(string(tomlDocument))
|
||||
var cfg config.AppConfig
|
||||
if err := toml.Unmarshal([]byte(docStr), &cfg); err != nil {
|
||||
ui.Warning("failed to parse Fes.toml", err)
|
||||
cfg = defaultCfg
|
||||
cfg.App.Authors = []string{"unknown"}
|
||||
cfg.App.Name = "unknown"
|
||||
cfg.App.Version = "unknown"
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
@@ -424,8 +414,6 @@ func Start(dir string) error {
|
||||
return ui.Error(fmt.Sprintf("failed to change directory to %s", dir), err)
|
||||
}
|
||||
|
||||
ui.Log("Running root=%s, port=%d.", filepath.Clean(dir), *config.Port)
|
||||
|
||||
cfg := parseConfig()
|
||||
notFoundData := generateNotFoundData(&cfg)
|
||||
routes := loadDirs()
|
||||
@@ -477,8 +465,7 @@ func Start(dir string) error {
|
||||
|
||||
w.Write(data)
|
||||
})
|
||||
ui.Log("Server initialized")
|
||||
|
||||
ui.Log("Ready to accept connections tcp")
|
||||
fmt.Printf("Server is running on http://localhost:%d\n", *config.Port)
|
||||
return http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", *config.Port), nil)
|
||||
}
|
||||
|
||||
109
modules/ui/ui.go
109
modules/ui/ui.go
@@ -4,114 +4,61 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"fes/modules/config"
|
||||
"fes/modules/version"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
const (
|
||||
hintColor = 0xbda02a
|
||||
)
|
||||
|
||||
func formatTimestamp() string {
|
||||
return time.Now().Format("02 Jan 2006 15:04")
|
||||
}
|
||||
|
||||
func logMessage(prefix string, msg string, args ...any) {
|
||||
formatted := fmt.Sprintf(msg, args...)
|
||||
if prefix == "" {
|
||||
fmt.Printf("%s * %s\n", formatTimestamp(), formatted)
|
||||
} else {
|
||||
fmt.Printf("%s * %s: %s\n", formatTimestamp(), prefix, formatted)
|
||||
}
|
||||
}
|
||||
|
||||
// Generic log
|
||||
func Log(msg string, args ...any) {
|
||||
logMessage("", msg, args...)
|
||||
}
|
||||
|
||||
// OK message (green)
|
||||
func OK(msg string, args ...any) {
|
||||
formatted := fmt.Sprintf(msg, args...)
|
||||
color.Green("%s * %s\n", formatTimestamp(), formatted)
|
||||
}
|
||||
|
||||
// Warning message (magenta)
|
||||
func WARN(msg string, args ...any) {
|
||||
formatted := fmt.Sprintf(msg, args...)
|
||||
color.Magenta("%s # %s\n", formatTimestamp(), formatted)
|
||||
}
|
||||
|
||||
// Warning message (magenta)
|
||||
func WARNING(msg string, args ...any) {
|
||||
formatted := fmt.Sprintf(msg, args...)
|
||||
color.Magenta("%s # WARNING %s\n", formatTimestamp(), formatted)
|
||||
}
|
||||
|
||||
// Error message (red)
|
||||
func ERROR(msg string, args ...any) {
|
||||
formatted := fmt.Sprintf(msg, args...)
|
||||
color.Red("%s ! %s\n", formatTimestamp(), formatted)
|
||||
}
|
||||
|
||||
// Fatal message and panic
|
||||
func FATAL(msg string, args ...any) {
|
||||
formatted := fmt.Sprintf(msg, args...)
|
||||
color.Red("%s % %s\n", formatTimestamp(), formatted)
|
||||
panic(formatted)
|
||||
}
|
||||
|
||||
// Hint message (custom color)
|
||||
func Hint(msg string, args ...any) {
|
||||
formatted := fmt.Sprintf(msg, args...)
|
||||
color.RGB(func(hex int) (r, g, b int) {
|
||||
r = (hex >> 16) & 0xFF
|
||||
g = (hex >> 8) & 0xFF
|
||||
b = hex & 0xFF
|
||||
return
|
||||
}(hintColor)).Printf("%s * hint: %s\n", formatTimestamp(), formatted)
|
||||
}
|
||||
|
||||
// Path logging: prints route and status
|
||||
/* print out the current path (route) and relevant error */
|
||||
func Path(path string, err error) {
|
||||
path = strings.TrimPrefix(path, "/")
|
||||
|
||||
if path == "" {
|
||||
path = "(null)"
|
||||
}
|
||||
|
||||
fmt.Printf(" > %s ", path)
|
||||
if err == nil {
|
||||
OK("Route: %s - ok", path)
|
||||
OK("ok")
|
||||
return
|
||||
} else if errors.Is(err, config.ErrRouteMiss) {
|
||||
WARN("Route: %s - %s", path, config.ErrRouteMiss.Error())
|
||||
WARN(config.ErrRouteMiss.Error())
|
||||
} else {
|
||||
ERROR("Route: %s - bad", path)
|
||||
ERROR("bad")
|
||||
}
|
||||
}
|
||||
|
||||
// System warning with prefix
|
||||
/* print general system warning */
|
||||
func Warning(msg string, err error) error {
|
||||
WARN("%s: %v", msg, err)
|
||||
fmt.Printf("%s: %s: %v\n", version.PROGRAM_NAME, color.MagentaString("warning"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
// System error with prefix
|
||||
/* print general system error */
|
||||
func Error(msg string, err error) error {
|
||||
ERROR("%s: %v", msg, err)
|
||||
fmt.Printf("%s: %s: %v\n", version.PROGRAM_NAME, color.RedString("error"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Fatal system error
|
||||
/* print fatality and panic */
|
||||
func Fatal(msg string, err error) error {
|
||||
FATAL("%s: %v", msg, err)
|
||||
return err
|
||||
fmt.Printf("%s: %s: %v\n", version.PROGRAM_NAME, color.RedString("fatal"), err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Log on Verbose
|
||||
func LogVerbose(msg string, args ...any) {
|
||||
if *config.Verbose {
|
||||
Log(msg, args...)
|
||||
}
|
||||
/* print message using the ok status color */
|
||||
func OK(msg string) {
|
||||
color.Green(msg)
|
||||
}
|
||||
|
||||
/* print message using the warning status color */
|
||||
func WARN(msg string) {
|
||||
color.Magenta(msg)
|
||||
}
|
||||
|
||||
/* print message using the error status color */
|
||||
func ERROR(msg string) {
|
||||
color.Red(msg)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ var gitCommit string = "devel"
|
||||
|
||||
const PROGRAM_NAME string = "fes"
|
||||
const PROGRAM_NAME_LONG string = "fes/fSD"
|
||||
const VERSION string = "0.2.0"
|
||||
const VERSION string = "beta"
|
||||
|
||||
func Version() {
|
||||
fmt.Printf("%s version %s\n", PROGRAM_NAME_LONG, VERSION)
|
||||
@@ -20,7 +20,3 @@ func FullVersion() {
|
||||
fmt.Printf("%s+%s\n", VERSION, gitCommit)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func GetCommit() string {
|
||||
return gitCommit
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user