commit fe630405277c63b0be494a89cda68f0e2d168be3
parent 070bf5debe4a9bfc0bc63d90ccad03ca2476d695
Author: weetat <wtenison@protonmail.com>
Date: Wed, 26 Feb 2025 22:18:40 +0000
Split filesystem.go into directories.go and files.go
Also unexport the fmd token types.
Diffstat:
7 files changed, 209 insertions(+), 177 deletions(-)
diff --git a/src/filesystem/directories.go b/src/filesystem/directories.go
@@ -0,0 +1,129 @@
+package filesystem
+
+import (
+ "fmt"
+ "log"
+ "miki/src/fmd"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+type SearchDepth int
+
+const (
+ // NOTE: Should I have an INF option?
+ SEARCH_DEPTH_INF SearchDepth = -1
+ SEARCH_DEPTH_ZERO SearchDepth = 0
+)
+
+type DirectorySignature struct {
+ Root string // The root directoy of the resource.
+ DependencyDepth SearchDepth // The folder search depth of the resource. -1=inf, 0=single, >0=n-depth
+ DependencyPattern *regexp.Regexp // The pattern of valid resource dependency files.
+}
+
+type DirectoryPackage struct {
+ Root string // The root directory of the resource.
+ DependencyFiles []string // The set of valid resource files.
+ DependencyData interface{} // Any relevant resource data.
+}
+
+func MakeDirectorySig(directory string, depth SearchDepth, pattern *regexp.Regexp) (DirectorySignature, error) {
+
+ if directory == "" || depth < -1 || pattern == nil {
+ _retErr := fmt.Errorf("MakeDirectorySig:invalid directory signature (%s, %d, %s)", directory, depth, pattern)
+ return DirectorySignature{}, _retErr
+ }
+
+ if _, _err := os.Stat(directory); _err != nil {
+ _retErr := fmt.Errorf("MakeDirectorySig:%s", _err)
+ return DirectorySignature{}, _retErr
+ }
+
+ return DirectorySignature{directory, depth, pattern}, nil
+}
+
+func MakeDirectoryPkg(resSig DirectorySignature) (DirectoryPackage, error) {
+
+ // Check and collect resource signature directory files.
+ _files, _err := os.ReadDir(resSig.Root)
+ if _err != nil {
+ _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
+ return DirectoryPackage{}, _retErr
+ }
+
+ _resPkg := DirectoryPackage{
+ Root: resSig.Root,
+ DependencyFiles: []string{},
+ DependencyData: nil,
+ }
+
+ _resFileDirDeps := []string{}
+
+ // Collete all valid files and/or sub-directory files.
+ for _, _f := range _files {
+
+ // Recurse into valid sub-directory files.
+ if _f.IsDir() && (resSig.DependencyDepth > SEARCH_DEPTH_ZERO || resSig.DependencyDepth == SEARCH_DEPTH_INF) {
+
+ // Decrement depth if not infinite.
+ _depDepth := resSig.DependencyDepth
+ if _depDepth != SEARCH_DEPTH_INF {
+ _depDepth = _depDepth - 1
+ }
+
+ // Make directory signature for each sub-file/dir
+ _resDirSig, _err := MakeDirectorySig(_f.Name(), _depDepth, resSig.DependencyPattern)
+ if _err != nil {
+ _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
+ return DirectoryPackage{}, _retErr
+ }
+
+ // Make the respective package.
+ _resDirPkg, _err := MakeDirectoryPkg(_resDirSig)
+ if _err != nil {
+ _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
+ return DirectoryPackage{}, _retErr
+ }
+
+ // Add to package dependencies list.
+ _resFileDirDeps = append(_resFileDirDeps, _resDirPkg.DependencyFiles...)
+
+ } else if resSig.DependencyPattern != nil && resSig.DependencyPattern.MatchString(_f.Name()) {
+ // Add files that match pattern to dependency list.
+ _resPkg.DependencyFiles = append(_resPkg.DependencyFiles, filepath.Join(_resPkg.Root, _f.Name()))
+ }
+ }
+
+ // Include any sub-directory file dependencies.
+ _resPkg.DependencyFiles = append(_resPkg.DependencyFiles, _resFileDirDeps...)
+
+ // Check for atricle entry.
+ // TODO: Move to secure and refined interface.
+ _dataFiles, _err := os.ReadDir(Dirs["data"])
+ if _err != nil {
+ _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
+ return DirectoryPackage{}, _retErr
+ }
+
+ for _, _df := range _dataFiles {
+ _rootFile := strings.Split(resSig.Root, "/")
+ _rootDataFile := _rootFile[len(_rootFile)-1] + ".fmd"
+
+ if _df.Name() == _rootDataFile {
+ log.Printf("INFO\tMakeDirectoryPkg:df:%s, rootDataFile:%s", _df.Name(), _rootDataFile)
+
+ var _DataContainer struct {
+ PageContent string
+ }
+
+ _DataContainer.PageContent = fmd.WritFMDToHTMLString(filepath.Join(Dirs["data"], _rootDataFile))
+
+ _resPkg.DependencyData = _DataContainer
+ }
+ }
+
+ return _resPkg, nil
+}
diff --git a/src/filesystem/files.go b/src/filesystem/files.go
@@ -0,0 +1,25 @@
+package filesystem
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "regexp"
+)
+
+var FilePatternHTML = regexp.MustCompile("^([a-zA-Z0-9.]+).html$")
+var FilePatternJSON = regexp.MustCompile("^([a-zA-Z0-9.]+).json$")
+
+func ReadFileJSON(filePath string, outputDataContainer interface{}) error {
+
+ _fsData, _err := os.ReadFile("sys/config.json")
+ if _err != nil {
+ return fmt.Errorf("_ERROR\tfilesystem:ReadFileJSON:os.ReadFile:%s:%s", filePath, _err.Error())
+ }
+
+ if _err = json.Unmarshal(_fsData, &outputDataContainer); _err != nil {
+ return fmt.Errorf("_ERROR\tfilesystem:ReadFileJSON:json.Unmarshal:%s:%s", filePath, _err.Error())
+ }
+
+ return nil
+}
diff --git a/src/filesystem/filesystem.go b/src/filesystem/filesystem.go
@@ -1,166 +1,44 @@
package filesystem
import (
- "encoding/json"
- "fmt"
"log"
- "miki/src/fmd"
- "os"
"path/filepath"
- "regexp"
- "strings"
)
-var FilePatternHTML = regexp.MustCompile("^([a-zA-Z0-9.]+).html$")
+// var Dirs map[string]string
+var Dirs = make(map[string]string)
-var Dirs struct {
- DataDirectory string `json:"data-directory"`
- WebDirectory string `json:"web-directory"`
-}
-
-var GlobalPkg DirectoryPackage
-
-type DirectorySignature struct {
- Root string // The root directoy of the resource.
- DependencyDepth int // The folder search depth of the resource. -1=inf, 0=single, >0=n-depth
- DependencyPattern *regexp.Regexp // The pattern of valid resource dependency files.
-}
-
-type DirectoryPackage struct {
- Root string // The root directory of the resource.
- DependencyFiles []string // The set of valid resource files.
- DependencyData interface{} // Any relevant resource data.
-}
-
-type IDirectoryData interface {
-}
-
-func MakeDirectorySig(directory string, depth int, pattern *regexp.Regexp) (DirectorySignature, error) {
-
- if directory == "" || depth < -1 || pattern == nil {
- _retErr := fmt.Errorf("MakeDirectorySig:invalid directory signature (%s, %d, %s)", directory, depth, pattern)
- return DirectorySignature{}, _retErr
- }
-
- if _, _err := os.Stat(directory); _err != nil {
- _retErr := fmt.Errorf("MakeDirectorySig:%s", _err)
- return DirectorySignature{}, _retErr
- }
-
- return DirectorySignature{directory, depth, pattern}, nil
-}
-
-func MakeDirectoryPkg(resSig DirectorySignature) (DirectoryPackage, error) {
-
- // Check and collect resource signature directory files.
- _files, _err := os.ReadDir(resSig.Root)
- if _err != nil {
- _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
- return DirectoryPackage{}, _retErr
- }
-
- _resPkg := DirectoryPackage{
- Root: resSig.Root,
- DependencyFiles: []string{},
- DependencyData: nil,
- }
-
- _resFileDirDeps := []string{}
-
- // Collete all valid files and/or sub-directory files.
- for _, _f := range _files {
-
- if _f.IsDir() && (resSig.DependencyDepth > 0 || resSig.DependencyDepth == -1) {
- // Recurse into valid sub-directory files.
-
- // Make directory signature for each sub-file/dir
- _resDirSig, _err := MakeDirectorySig(_f.Name(), resSig.DependencyDepth, resSig.DependencyPattern)
- if _err != nil {
- _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
- return DirectoryPackage{}, _retErr
- }
-
- // Make the respective package.
- _resDirPkg, _err := MakeDirectoryPkg(_resDirSig)
- if _err != nil {
- _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
- return DirectoryPackage{}, _retErr
- }
-
- // Add to package dependencies list.
- _resFileDirDeps = append(_resFileDirDeps, _resDirPkg.DependencyFiles...)
-
- } else if resSig.DependencyPattern != nil && resSig.DependencyPattern.MatchString(_f.Name()) {
- // Add files that match pattern to dependency list.
- _resPkg.DependencyFiles = append(_resPkg.DependencyFiles, filepath.Join(_resPkg.Root, _f.Name()))
- }
- }
-
- // Include any sub-directory file dependencies.
- _resPkg.DependencyFiles = append(_resPkg.DependencyFiles, _resFileDirDeps...)
-
- // Check for atricle entry.
- // TODO: Move to secure and refined interface.
- _dataFiles, _err := os.ReadDir(Dirs.DataDirectory)
- if _err != nil {
- _retErr := fmt.Errorf("MakeDirectoryPkg:%s", _err)
- return DirectoryPackage{}, _retErr
- }
-
- for _, _df := range _dataFiles {
- _rootFile := strings.Split(resSig.Root, "/")
- _rootDataFile := _rootFile[len(_rootFile)-1] + ".fmd"
-
- if _df.Name() == _rootDataFile {
- log.Printf("INFO\tMakeDirectoryPkg:df:%s, rootDataFile:%s", _df.Name(), _rootDataFile)
-
- var _DataContainer struct {
- PageContent string
- }
-
- _DataContainer.PageContent = fmd.WritFMDToHTMLString(filepath.Join(Dirs.DataDirectory, _rootDataFile))
-
- _resPkg.DependencyData = _DataContainer
- }
- }
-
- return _resPkg, nil
-}
+var WebGlobalPkg DirectoryPackage
func Init() {
//// PULL SYSTEM INFO FROM JSON
- _fsData, _err := os.ReadFile("sys/config.json")
- if _err != nil {
- log.Panicln("__PANIC\tfilesystem:Init:os.ReadFile:config.json:" + _err.Error())
- return
- }
-
var _fsDataStruct struct {
DataDirectory string `json:"data-directory"`
WebDirectory string `json:"web-directory"`
}
- if _err = json.Unmarshal(_fsData, &_fsDataStruct); _err != nil {
- log.Panicln("__PANIC\tjson.Unmarshal:config.json:" + _err.Error())
- return
+ if _err := ReadFileJSON("sys/config.json", &_fsDataStruct); _err != nil {
+ log.Panicf("__PANIC\tfilesystem:%s", _err)
}
- Dirs.DataDirectory = _fsDataStruct.DataDirectory
- Dirs.WebDirectory = _fsDataStruct.WebDirectory
+ Dirs["data"] = _fsDataStruct.DataDirectory
+ Dirs["web"] = _fsDataStruct.WebDirectory
log.Printf("INFO\tfilesystem:Init:Dirs:%v\n", Dirs)
- //// GET GLOBAL DIRECTORY RESOURCES
+ //// GET GLOBAL WEB RESOURCES
- _globalSig, _err := MakeDirectorySig(filepath.Join(Dirs.WebDirectory, "/global"), 0, FilePatternHTML)
+ _globalSig, _err := MakeDirectorySig(filepath.Join(Dirs["web"], "/global"), 0, FilePatternHTML)
if _err != nil {
- log.Panicf("__PANIC\tfilesystem:Init:MakeDirectorySig:%s", _err)
+ log.Panicf("__PANIC\tfilesystem:Init:%s", _err)
}
- GlobalPkg, _err = MakeDirectoryPkg(_globalSig)
+ WebGlobalPkg, _err = MakeDirectoryPkg(_globalSig)
if _err != nil {
- log.Panicf("__PANIC\tfilesystem:Init:MakeDirectoryPkg:%s", _err)
+ log.Panicf("__PANIC\tfilesystem:Init:%s", _err)
}
+
+ log.Printf("INFO\tfilesystem:Init:WebGlobals:%v\n", Dirs)
}
diff --git a/src/fmd/interpreter.go b/src/fmd/interpreter.go
@@ -45,7 +45,7 @@ func interpret(n node) string {
return "<div>" + interpret(n.children[0]) + "</div>"
}
case nodeBlock:
- _res.WriteString("<div>")
+ _res.WriteString("<div class=\"__block\">")
for _, _child := range n.children {
_res.WriteString(interpret(_child))
}
diff --git a/src/fmd/lexer.go b/src/fmd/lexer.go
@@ -11,28 +11,28 @@ type tokenType int
const (
// WORDS
- TokenLiteral tokenType = iota // 0. (letters, numbers, symbols)+
- TokenKeyword // 1. (valid keywords)
+ tokenLiteral tokenType = iota // 0. (letters, numbers, symbols)+
+ tokenKeyword // 1. (valid keywords)
// SPACING
- TokenSpace // 2. " "
- TokenNewline // 3. \n
- TokenTab // 4. \t
- TokenEscape // 5. \
+ tokenSpace // 2. " "
+ tokenNewline // 3. \n
+ tokenTab // 4. \t
+ tokenEscape // 5. \
// OPERATORS
- TokenColon // 6. :
- TokenLBrace // 7. {
- TokenRBrace // 8. }
+ tokenColon // 6. :
+ tokenLBrace // 7. {
+ tokenRBrace // 8. }
)
type token struct {
- Type tokenType
+ tType tokenType
Value string
}
var symbols = []string{" ", "\n", "\t", "\\", ":", "{", "}"}
-var opKeywords = []string{
+var keywords = []string{
"b", "i", "h1", "h2", "h3", "h4", "h5", "h6", "@", "#", "col", "img", "_"}
type lexer struct {
@@ -52,25 +52,25 @@ func (l *lexer) Exec() []token {
switch {
case _currentSymbol == ' ':
- l.tokens = append(l.tokens, token{TokenSpace, " "})
+ l.tokens = append(l.tokens, token{tokenSpace, " "})
l.pos++
case _currentSymbol == '\n':
- l.tokens = append(l.tokens, token{TokenNewline, "\n"})
+ l.tokens = append(l.tokens, token{tokenNewline, "\n"})
l.pos++
case _currentSymbol == '\t':
- l.tokens = append(l.tokens, token{TokenTab, "\t"})
+ l.tokens = append(l.tokens, token{tokenTab, "\t"})
l.pos++
case _currentSymbol == '\\':
- l.tokens = append(l.tokens, token{TokenEscape, "\\"})
+ l.tokens = append(l.tokens, token{tokenEscape, "\\"})
l.pos++
case _currentSymbol == ':':
- l.tokens = append(l.tokens, token{TokenColon, ":"})
+ l.tokens = append(l.tokens, token{tokenColon, ":"})
l.pos++
case _currentSymbol == '{':
- l.tokens = append(l.tokens, token{TokenLBrace, "{"})
+ l.tokens = append(l.tokens, token{tokenLBrace, "{"})
l.pos++
case _currentSymbol == '}':
- l.tokens = append(l.tokens, token{TokenRBrace, "}"})
+ l.tokens = append(l.tokens, token{tokenRBrace, "}"})
l.pos++
default:
{ // NOTE: inlined check until good reason to abstract arrives.
@@ -83,10 +83,10 @@ func (l *lexer) Exec() []token {
_tokenString = string(l.input[_start:l.pos])
- if slices.Contains(opKeywords, _tokenString) {
- l.tokens = append(l.tokens, token{TokenKeyword, _tokenString})
+ if slices.Contains(keywords, _tokenString) {
+ l.tokens = append(l.tokens, token{tokenKeyword, _tokenString})
} else if _tokenString != "" {
- l.tokens = append(l.tokens, token{TokenLiteral, _tokenString})
+ l.tokens = append(l.tokens, token{tokenLiteral, _tokenString})
}
}
}
diff --git a/src/fmd/parser.go b/src/fmd/parser.go
@@ -46,18 +46,18 @@ func (p *parser) Exec() node {
func (p *parser) parseCommand() node {
_command := node{nType: nodeCommand}
- _keyword := p.consume(TokenKeyword)
+ _keyword := p.consume(tokenKeyword)
_command.value = _keyword.Value
- p.consume(TokenColon)
+ p.consume(tokenColon)
// keyword:{block}
- if p.peekNextN(TokenLBrace, 0) {
- p.consume(TokenLBrace)
+ if p.peekNextN(tokenLBrace, 0) {
+ p.consume(tokenLBrace)
_command.children = []node{p.parseBlock()}
- p.consume(TokenRBrace)
+ p.consume(tokenRBrace)
} else { // keyword:"literal"
_command.children = []node{p.parseLiteral()}
}
@@ -68,17 +68,17 @@ func (p *parser) parseCommand() node {
func (p *parser) parseBlock() node {
_block := node{nType: nodeBlock}
- for p.pos < len(p.tokens) && p.current().Type != TokenRBrace {
+ for p.pos < len(p.tokens) && p.current().tType != tokenRBrace {
if p.isNextCommand() { // keyword:?
_block.children = append(_block.children, p.parseCommand())
- } else if p.peekNextN(TokenSpace, 0) { // " "
+ } else if p.peekNextN(tokenSpace, 0) { // " "
_block.children = append(_block.children, node{nType: nodeSpace, value: " "})
p.pos++
- } else if p.peekNextN(TokenNewline, 0) { // "\n"
+ } else if p.peekNextN(tokenNewline, 0) { // "\n"
_block.children = append(_block.children, node{nType: nodeNewline, value: "\n"})
p.pos++
- } else if p.peekNextN(TokenTab, 0) { // "\t"
+ } else if p.peekNextN(tokenTab, 0) { // "\t"
// _block.children = append(_block.children, node{nType: nodeSpace, value: "\\t"})
p.pos++
} else { // "literal"
@@ -91,19 +91,19 @@ func (p *parser) parseBlock() node {
}
func (p *parser) parseLiteral() node {
- _literal := node{nType: nodeLiteral, value: p.consume(TokenLiteral).Value}
+ _literal := node{nType: nodeLiteral, value: p.consume(tokenLiteral).Value}
return _literal
}
func (p *parser) isNextCommand() bool {
- return p.peekNextN(TokenKeyword, 0) &&
- p.peekNextN(TokenColon, 1) &&
- p.peekNextN(TokenLiteral, 2) ||
- p.peekNextN(TokenLBrace, 2)
+ return p.peekNextN(tokenKeyword, 0) &&
+ p.peekNextN(tokenColon, 1) &&
+ p.peekNextN(tokenLiteral, 2) ||
+ p.peekNextN(tokenLBrace, 2)
}
func (p *parser) peekNextN(t tokenType, n int) bool {
- _res := p.pos+n < len(p.tokens) && p.tokens[p.pos+n].Type == t
+ _res := p.pos+n < len(p.tokens) && p.tokens[p.pos+n].tType == t
return _res
}
diff --git a/src/network/network.go b/src/network/network.go
@@ -24,7 +24,7 @@ var mux *http.ServeMux
func handlePageDefault(w http.ResponseWriter, r *http.Request) {
// Produce URL path to directory relation.
- _r, _err := mfs.MakeDirectorySig(filepath.Join(mfs.Dirs.WebDirectory, r.URL.String()), 0, mfs.FilePatternHTML)
+ _r, _err := mfs.MakeDirectorySig(filepath.Join(mfs.Dirs["web"], r.URL.String()), 0, mfs.FilePatternHTML)
if _err != nil {
log.Printf("_ERROR\tnetwork:handlePageDefault(\"/\"):%s\n", _err)
http.NotFound(w, r)
@@ -40,7 +40,7 @@ func handlePageDefault(w http.ResponseWriter, r *http.Request) {
}
// Add 'global' file dependencies.
- _rPkg.DependencyFiles = append(_rPkg.DependencyFiles, mfs.GlobalPkg.DependencyFiles...)
+ _rPkg.DependencyFiles = append(_rPkg.DependencyFiles, mfs.WebGlobalPkg.DependencyFiles...)
// Create template from package.
_tmpl, _err := template.ParseFiles(_rPkg.DependencyFiles...)
@@ -108,10 +108,10 @@ func Init() {
mux = http.NewServeMux()
- mux.Handle("/web/", http.StripPrefix("/web/", http.FileServer(http.Dir(mfs.Dirs.WebDirectory))))
+ mux.Handle("/web/", http.StripPrefix("/web/", http.FileServer(http.Dir(mfs.Dirs["web"]))))
mux.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
- http.ServeFile(w, r, filepath.Join(mfs.Dirs.WebDirectory, "/global/favicon.ico"))
+ http.ServeFile(w, r, filepath.Join(mfs.Dirs["web"], "/global/favicon.ico"))
})
mux.HandleFunc("/home", handlePageDefault)