Moved the create statement into the TopicStore.

Refactored the template generator.
Began improving Cosora again.
This commit is contained in:
Azareal 2017-11-07 22:38:15 +00:00
parent 569b424ac8
commit e2c48c58ba
13 changed files with 282 additions and 327 deletions

View File

@ -45,7 +45,6 @@ type Stmts struct {
getForumTopics *sql.Stmt getForumTopics *sql.Stmt
getProfileReplies *sql.Stmt getProfileReplies *sql.Stmt
getWatchers *sql.Stmt getWatchers *sql.Stmt
createTopic *sql.Stmt
createReport *sql.Stmt createReport *sql.Stmt
createActionReply *sql.Stmt createActionReply *sql.Stmt
createLike *sql.Stmt createLike *sql.Stmt
@ -388,13 +387,6 @@ func _gen_mssql() (err error) {
return err return err
} }
log.Print("Preparing createTopic statement.")
stmts.createTopic, err = db.Prepare("INSERT INTO [topics] ([parentID],[title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[ipaddress],[words],[createdBy]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?,?)")
if err != nil {
log.Print("Bad Query: ","INSERT INTO [topics] ([parentID],[title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[ipaddress],[words],[createdBy]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?,?)")
return err
}
log.Print("Preparing createReport statement.") log.Print("Preparing createReport statement.")
stmts.createReport, err = db.Prepare("INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[createdBy],[lastReplyBy],[data],[parentID],[css_class]) VALUES (?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?,1,'report')") stmts.createReport, err = db.Prepare("INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[createdBy],[lastReplyBy],[data],[parentID],[css_class]) VALUES (?,?,?,GETUTCDATE(),GETUTCDATE(),?,?,?,1,'report')")
if err != nil { if err != nil {

View File

@ -47,7 +47,6 @@ type Stmts struct {
getForumTopics *sql.Stmt getForumTopics *sql.Stmt
getProfileReplies *sql.Stmt getProfileReplies *sql.Stmt
getWatchers *sql.Stmt getWatchers *sql.Stmt
createTopic *sql.Stmt
createReport *sql.Stmt createReport *sql.Stmt
createActionReply *sql.Stmt createActionReply *sql.Stmt
createLike *sql.Stmt createLike *sql.Stmt
@ -353,12 +352,6 @@ func _gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing createTopic statement.")
stmts.createTopic, err = db.Prepare("INSERT INTO `topics`(`parentID`,`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`lastReplyBy`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?)")
if err != nil {
return err
}
log.Print("Preparing createReport statement.") log.Print("Preparing createReport statement.")
stmts.createReport, err = db.Prepare("INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`createdBy`,`lastReplyBy`,`data`,`parentID`,`css_class`) VALUES (?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,1,'report')") stmts.createReport, err = db.Prepare("INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`createdBy`,`lastReplyBy`,`data`,`parentID`,`css_class`) VALUES (?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,1,'report')")
if err != nil { if err != nil {

12
main.go
View File

@ -94,6 +94,18 @@ func main() {
} }
}()*/ }()*/
// WIP: Mango Test
/*res, err := ioutil.ReadFile("./templates/topic.html")
if err != nil {
log.Fatal(err)
}
tagIndices, err := mangoParse(string(res))
if err != nil {
log.Fatal(err)
}
log.Printf("tagIndices: %+v\n", tagIndices)
log.Fatal("")*/
// TODO: Have a file for each run with the time/date the server started as the file name? // TODO: Have a file for each run with the time/date the server started as the file name?
// TODO: Log panics with recover() // TODO: Log panics with recover()
f, err := os.OpenFile("./operations.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) f, err := os.OpenFile("./operations.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)

View File

@ -778,7 +778,7 @@ func TestProfileReplyStore(t *testing.T) {
recordMustNotExist(t, err, "PRID #0 shouldn't exist") recordMustNotExist(t, err, "PRID #0 shouldn't exist")
_, err = prstore.Get(1) _, err = prstore.Get(1)
recordMustNotExist(t, err, "PRID #0 shouldn't exist") recordMustNotExist(t, err, "PRID #1 shouldn't exist")
var profileID = 1 var profileID = 1
prid, err := prstore.Create(profileID, "Haha", 1, "::1") prid, err := prstore.Create(profileID, "Haha", 1, "::1")

View File

@ -657,7 +657,6 @@ func routeBanSubmit(w http.ResponseWriter, r *http.Request, user User) RouteErro
if uid == user.ID { if uid == user.ID {
return LocalError("Why are you trying to ban yourself? Stop that.", w, r, user) return LocalError("Why are you trying to ban yourself? Stop that.", w, r, user)
} }
if targetUser.IsBanned { if targetUser.IsBanned {
return LocalError("The user you're trying to unban is already banned.", w, r, user) return LocalError("The user you're trying to unban is already banned.", w, r, user)
} }

View File

@ -163,13 +163,7 @@ func (build *accBuilder) SimpleInsertSelectTx(tx *sql.Tx, ins DB_Insert, sel DB_
func (build *accBuilder) SimpleInsertLeftJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) { func (build *accBuilder) SimpleInsertLeftJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsertLeftJoin("_builder", ins, sel) res, err := build.adapter.SimpleInsertLeftJoin("_builder", ins, sel)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleInsertInnerJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) { func (build *accBuilder) SimpleInsertInnerJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) {

View File

@ -63,7 +63,6 @@ func (build *builder) SimpleCount(table string, where string, limit string) (stm
if err != nil { if err != nil {
return stmt, err return stmt, err
} }
//log.Print("res",res)
return build.conn.Prepare(res) return build.conn.Prepare(res)
} }
@ -72,7 +71,6 @@ func (build *builder) SimpleLeftJoin(table1 string, table2 string, columns strin
if err != nil { if err != nil {
return stmt, err return stmt, err
} }
//log.Print("res",res)
return build.conn.Prepare(res) return build.conn.Prepare(res)
} }
@ -81,7 +79,6 @@ func (build *builder) SimpleInnerJoin(table1 string, table2 string, columns stri
if err != nil { if err != nil {
return stmt, err return stmt, err
} }
//log.Print("res",res)
return build.conn.Prepare(res) return build.conn.Prepare(res)
} }

View File

@ -314,8 +314,6 @@ func writeInnerJoins(adapter qgen.DB_Adapter) (err error) {
} }
func writeInserts(adapter qgen.DB_Adapter) error { func writeInserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("createTopic", "topics", "parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?")
adapter.SimpleInsert("createReport", "topics", "title, content, parsed_content, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,1,'report'") adapter.SimpleInsert("createReport", "topics", "title, content, parsed_content, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,1,'report'")
adapter.SimpleInsert("createActionReply", "replies", "tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''") adapter.SimpleInsert("createActionReply", "replies", "tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''")

View File

@ -1,69 +1,48 @@
//+build experiment //+lbuild experiment
// ! EXPERIMENTAL // ! EXPERIMENTAL
package main package main
import ( import (
"errors" "errors"
"log"
"regexp" "regexp"
"text/template/parse"
) )
var tagFinder *regexp.Regexp type Mango struct {
var limeFuncMap = map[string]interface{}{ tagFinder *regexp.Regexp
"and": "&&",
"not": "!",
"or": "||",
"eq": true,
"ge": true,
"gt": true,
"le": true,
"lt": true,
"ne": true,
"add": true,
"subtract": true,
"multiply": true,
"divide": true,
} }
func init() { func (m *Mango) Init() {
tagFinder = regexp.MustCompile(`(?s)\{\{(.*)\}\}`) m.tagFinder = regexp.MustCompile(`(?s)\{\{(.*)\}\}`)
} }
func mangoParse(tmpl string) error { func (m *Mango) Parse(tmpl string) (out string, err error) {
tree := parse.New(name, funcMap) tagIndices := m.tagFinder.FindAllStringIndex(tmpl, -1)
var treeSet = make(map[string]*parse.Tree) if len(tagIndices) > 0 {
tree, err = tree.Parse(content, "{{", "}}", treeSet, limeFuncMap)
if err != nil {
return err
}
treeLength := len(tree.Root.Nodes)
log.Print("treeLength", treeLength)
return nil
}
func icecreamSoup(tmpl string) error {
if config.MinifyTemplates {
tmpl = minify(tmpl)
}
tagIndices := tagFinder.FindAllStringIndex(tmpl, -1)
if tagIndices != nil && len(tagIndices) > 0 {
if tagIndices[0][0] == 0 { if tagIndices[0][0] == 0 {
return errors.New("We don't support tags in the outermost layer yet") return "", errors.New("We don't support tags in the outermost layer yet")
} }
var lastTag = 0
var lastID = 0
for _, tagIndex := range tagIndices { for _, tagIndex := range tagIndices {
var nestingLayer = 0 var nestingLayer = 0
for i := tagIndex[0]; i > 0; i-- { for i := tagIndex[0]; i > 0; i-- {
switch tmpl[i] { switch tmpl[i] {
case '>': case '>':
i, closeTag, err := tasteTagToLeft(tmpl, i) ii, closeTag, err := m.tasteTagToLeft(tmpl, i)
if err != nil { if err != nil {
return err return "", err
} }
if closeTag { if closeTag {
nestingLayer++ nestingLayer++
} else {
_, tagID := m.parseTag(tmpl, ii, i)
if tagID == "" {
out += tmpl[lastTag:ii] + m.injectID(ii, i)
lastID++
} else {
out += tmpl[lastTag:i]
}
} }
case '<': case '<':
@ -71,9 +50,55 @@ func icecreamSoup(tmpl string) error {
} }
} }
} }
return "", nil
} }
func tasteTagToLeft(tmpl string, index int) (indexOut int, closeTag bool, err error) { func (m *Mango) injectID(start int, end int) string {
return ""
}
func (m *Mango) parseTag(tmpl string, start int, end int) (tagType string, tagID string) {
var i = start
for ; i < end; i++ {
if tmpl[i] == ' ' {
break
}
}
tagType = tmpl[start:i]
i = start
for ; i < (end - 4); i++ {
if tmpl[i] == ' ' && tmpl[i+1] == 'i' && tmpl[i+2] == 'd' && tmpl[i+3] == '=' {
tagID = m.extractAttributeContents(tmpl, i+4, end)
}
}
return tagType, tagID
}
func (m *Mango) extractAttributeContents(tmpl string, i int, end int) (contents string) {
var start = i
var quoteChar byte = 0 // nolint
if m.isHTMLQuoteChar(tmpl[i]) {
i++
quoteChar = tmpl[i]
}
i += 3
for ; i < end; i++ {
if quoteChar != 0 {
if tmpl[i] == quoteChar {
break
}
} else if tmpl[i] == ' ' {
break
}
}
return tmpl[start:i]
}
func (m *Mango) isHTMLQuoteChar(char byte) bool {
return char == '\'' || char == '"'
}
func (m *Mango) tasteTagToLeft(tmpl string, index int) (indexOut int, closeTag bool, err error) {
var foundLeftBrace = false var foundLeftBrace = false
for ; index > 0; index-- { for ; index > 0; index-- {
// What if the / isn't adjacent to the < but has a space instead? Is that even valid? // What if the / isn't adjacent to the < but has a space instead? Is that even valid?
@ -85,7 +110,7 @@ func tasteTagToLeft(tmpl string, index int) (indexOut int, closeTag bool, err er
} }
} }
if !foundLeftBrace { if !foundLeftBrace {
return errors.New("The left portion of the tag is missing") return index, closeTag, errors.New("The left portion of the tag is missing")
} }
return index, closeTag, nil return index, closeTag, nil
} }

View File

@ -60,6 +60,7 @@ func Route(fname string, path string, args ...string) *RouteImpl {
return &RouteImpl{fname, path, args, []Runnable{}} return &RouteImpl{fname, path, args, []Runnable{}}
} }
// TODO: How should we handle headerLite and headerVar?
func routes() { func routes() {
//addRoute("default_route","","") //addRoute("default_route","","")
addRoute(Route("routeAPI", "/api/")) addRoute(Route("routeAPI", "/api/"))

View File

@ -144,12 +144,12 @@ func (c *CTemplateSet) compileTemplate(name string, dir string, expects string,
w.Write([]byte(`, " + ", -1) w.Write([]byte(`, " + ", -1)
fout = strings.Replace(fout, "` + `", "", -1) fout = strings.Replace(fout, "` + `", "", -1)
//spstr := "`([:space:]*)`" //spstr := "`([:space:]*)`"
//whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`) //whitespaceWrites := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`)
//fout = whitespace_writes.ReplaceAllString(fout,"") //fout = whitespaceWrites.ReplaceAllString(fout,"")
if dev.DebugMode { if dev.DebugMode {
for index, count := range c.stats { for index, count := range c.stats {
fmt.Println(index + ": " + strconv.Itoa(count)) fmt.Println(index+": ", strconv.Itoa(count))
} }
fmt.Println(" ") fmt.Println(" ")
} }
@ -158,6 +158,7 @@ w.Write([]byte(`, " + ", -1)
fmt.Println("Output!") fmt.Println("Output!")
fmt.Println(fout) fmt.Println(fout)
} }
//log.Fatal("remove the log.Fatal line")
return fout, nil return fout, nil
} }
@ -170,7 +171,6 @@ func (c *CTemplateSet) rootIterate(tree *parse.Tree, varholder string, holdrefle
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("Node:", node.String()) fmt.Println("Node:", node.String())
} }
c.previousNode = c.currentNode c.previousNode = c.currentNode
c.currentNode = node.Type() c.currentNode = node.Type()
if treeLength != (index + 1) { if treeLength != (index + 1) {
@ -181,7 +181,7 @@ func (c *CTemplateSet) rootIterate(tree *parse.Tree, varholder string, holdrefle
return out return out
} }
func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value, templateName string, node interface{}) (out string) { func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value, templateName string, node parse.Node) (out string) {
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("in compileSwitch") fmt.Println("in compileSwitch")
} }
@ -196,7 +196,6 @@ func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value
for _, cmd := range node.Pipe.Cmds { for _, cmd := range node.Pipe.Cmds {
out += c.compileSubswitch(varholder, holdreflect, templateName, cmd) out += c.compileSubswitch(varholder, holdreflect, templateName, cmd)
} }
return out
case *parse.IfNode: case *parse.IfNode:
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("If Node:") fmt.Println("If Node:")
@ -218,7 +217,6 @@ func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("If Node Expression:", expr) fmt.Println("If Node Expression:", expr)
} }
c.previousNode = c.currentNode c.previousNode = c.currentNode
c.currentNode = parse.NodeList c.currentNode = parse.NodeList
c.nextNode = -1 c.nextNode = -1
@ -240,8 +238,34 @@ func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value
for _, subnode := range node.Nodes { for _, subnode := range node.Nodes {
out += c.compileSwitch(varholder, holdreflect, templateName, subnode) out += c.compileSwitch(varholder, holdreflect, templateName, subnode)
} }
return out
case *parse.RangeNode: case *parse.RangeNode:
return c.compileRangeNode(varholder, holdreflect, templateName, node)
case *parse.TemplateNode:
return c.compileSubtemplate(varholder, holdreflect, node)
case *parse.TextNode:
c.previousNode = c.currentNode
c.currentNode = node.Type()
c.nextNode = 0
tmpText := bytes.TrimSpace(node.Text)
if len(tmpText) == 0 {
return ""
}
fragmentName := templateName + "_" + strconv.Itoa(c.FragmentCursor[templateName])
_, ok := c.Fragments[fragmentName]
if !ok {
c.Fragments[fragmentName] = len(node.Text)
c.FragOut += "var " + fragmentName + " = []byte(`" + string(node.Text) + "`)\n"
}
c.FragmentCursor[templateName] = c.FragmentCursor[templateName] + 1
return "w.Write(" + fragmentName + ")\n"
default:
return c.unknownNode(node)
}
return out
}
func (c *CTemplateSet) compileRangeNode(varholder string, holdreflect reflect.Value, templateName string, node *parse.RangeNode) (out string) {
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("Range Node!") fmt.Println("Range Node!")
fmt.Println(node.Pipe) fmt.Println(node.Pipe)
@ -254,7 +278,6 @@ func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value
} }
out, outVal = c.compileReflectswitch(varholder, holdreflect, templateName, cmd) out, outVal = c.compileReflectswitch(varholder, holdreflect, templateName, cmd)
} }
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("Returned:", out) fmt.Println("Returned:", out)
fmt.Println("Range Kind Switch!") fmt.Println("Range Kind Switch!")
@ -289,35 +312,9 @@ func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value
} }
if node.ElseList != nil { if node.ElseList != nil {
out += " else {\n" + c.compileSwitch(varholder, holdreflect, templateName, node.ElseList) + "}\n" out += " else {\n" + c.compileSwitch(varholder, holdreflect, templateName, node.ElseList) + "}"
} else {
out += "\n"
} }
return out return out + "\n"
case *parse.TemplateNode:
return c.compileSubtemplate(varholder, holdreflect, node)
case *parse.TextNode:
c.previousNode = c.currentNode
c.currentNode = node.Type()
c.nextNode = 0
tmpText := bytes.TrimSpace(node.Text)
if len(tmpText) == 0 {
return ""
}
//return "w.Write([]byte(`" + string(node.Text) + "`))\n"
fragmentName := templateName + "_" + strconv.Itoa(c.FragmentCursor[templateName])
_, ok := c.Fragments[fragmentName]
if !ok {
c.Fragments[fragmentName] = len(node.Text)
c.FragOut += "var " + fragmentName + " = []byte(`" + string(node.Text) + "`)\n"
}
c.FragmentCursor[templateName] = c.FragmentCursor[templateName] + 1
return "w.Write(" + fragmentName + ")\n"
default:
panic("Unknown Node in main switch")
}
return ""
} }
func (c *CTemplateSet) compileSubswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string) { func (c *CTemplateSet) compileSubswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string) {
@ -353,7 +350,6 @@ func (c *CTemplateSet) compileSubswitch(varholder string, holdreflect reflect.Va
for cur.Kind() == reflect.Ptr { for cur.Kind() == reflect.Ptr {
cur = cur.Elem() cur = cur.Elem()
} }
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("Data Kind:", cur.Kind().String()) fmt.Println("Data Kind:", cur.Kind().String())
fmt.Println("Field Bit:", id) fmt.Println("Field Bit:", id)
@ -364,7 +360,7 @@ func (c *CTemplateSet) compileSubswitch(varholder string, holdreflect reflect.Va
if dev.DebugMode { if dev.DebugMode {
fmt.Println("Debug Data:") fmt.Println("Debug Data:")
fmt.Println("Holdreflect:", holdreflect) fmt.Println("Holdreflect:", holdreflect)
fmt.Println("Holdreflect.Kind()", holdreflect.Kind()) fmt.Println("Holdreflect.Kind():", holdreflect.Kind())
if !dev.TemplateDebug { if !dev.TemplateDebug {
fmt.Println("cur.Kind():", cur.Kind().String()) fmt.Println("cur.Kind():", cur.Kind().String())
} }
@ -425,15 +421,13 @@ func (c *CTemplateSet) compileSubswitch(varholder string, holdreflect reflect.Va
} }
return c.compileVarsub(c.compileIdentswitch(varholder, holdreflect, templateName, node)) return c.compileVarsub(c.compileIdentswitch(varholder, holdreflect, templateName, node))
default: default:
fmt.Println("Unknown Kind:", reflect.ValueOf(firstWord).Elem().Kind()) return c.unknownNode(node)
fmt.Println("Unknown Type:", reflect.ValueOf(firstWord).Elem().Type().Name())
panic("I don't know what node this is")
} }
} }
func (c *CTemplateSet) compileVarswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string) { func (c *CTemplateSet) compileVarswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string) {
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("in compile_varswitch") fmt.Println("in compileVarswitch")
} }
firstWord := node.Args[0] firstWord := node.Args[0]
switch n := firstWord.(type) { switch n := firstWord.(type) {
@ -466,7 +460,6 @@ func (c *CTemplateSet) compileVarswitch(varholder string, holdreflect reflect.Va
fmt.Println("Variable Node Identifier:", n.Ident) fmt.Println("Variable Node Identifier:", n.Ident)
} }
out, _ = c.compileIfVarsub(n.String(), varholder, templateName, holdreflect) out, _ = c.compileIfVarsub(n.String(), varholder, templateName, holdreflect)
return out
case *parse.NilNode: case *parse.NilNode:
panic("Nil is not a command x.x") panic("Nil is not a command x.x")
case *parse.PipeNode: case *parse.PipeNode:
@ -480,12 +473,16 @@ func (c *CTemplateSet) compileVarswitch(varholder string, holdreflect reflect.Va
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("Out:", out) fmt.Println("Out:", out)
} }
return out
default: default:
fmt.Println("Unknown Kind:", reflect.ValueOf(firstWord).Elem().Kind()) return c.unknownNode(firstWord)
fmt.Println("Unknown Type:", reflect.ValueOf(firstWord).Elem().Type().Name())
panic("I don't know what node this is! Grr...")
} }
return out
}
func (c *CTemplateSet) unknownNode(node parse.Node) (out string) {
fmt.Println("Unknown Kind:", reflect.ValueOf(node).Elem().Kind())
fmt.Println("Unknown Type:", reflect.ValueOf(node).Elem().Type().Name())
panic("I don't know what node this is! Grr...")
return "" return ""
} }
@ -497,6 +494,78 @@ func (c *CTemplateSet) compileIdentswitchN(varholder string, holdreflect reflect
return out return out
} }
func (c *CTemplateSet) compareFunc(varholder string, holdreflect reflect.Value, templateName string, pos int, node *parse.CommandNode, compare string) (out string) {
if dev.TemplateDebug {
fmt.Println("symbol: ", compare)
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
return c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " " + compare + " " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect)
}
func (c *CTemplateSet) simpleMath(varholder string, holdreflect reflect.Value, templateName string, pos int, node *parse.CommandNode, symbol string) (out string, val reflect.Value) {
leftParam, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect)
rightParam, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect)
if val2.IsValid() {
val = val2
} else if val3.IsValid() {
val = val3
} else {
// TODO: What does this do?
numSample := 1
val = reflect.ValueOf(numSample)
}
if dev.TemplateDebug {
fmt.Println("symbol: " + symbol)
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
return leftParam + " " + symbol + " " + rightParam, val
}
func (c *CTemplateSet) compareJoin(varholder string, holdreflect reflect.Value, templateName string, pos int, node *parse.CommandNode, symbol string) (pos2 int, out string) {
if dev.TemplateDebug {
fmt.Println("Building " + symbol + " function")
}
if pos == 0 {
fmt.Println("pos:", pos)
panic(symbol + " is missing a left operand")
}
if len(node.Args) <= pos {
fmt.Println("post pos:", pos)
fmt.Println("len(node.Args):", len(node.Args))
panic(symbol + " is missing a right operand")
}
left := c.compileBoolsub(node.Args[pos-1].String(), varholder, templateName, holdreflect)
_, funcExists := c.funcMap[node.Args[pos+1].String()]
var right string
if !funcExists {
right = c.compileBoolsub(node.Args[pos+1].String(), varholder, templateName, holdreflect)
}
out = left + " " + symbol + " " + right
//log.Print("left: ", left)
//log.Print("right: ", right)
if dev.TemplateDebug {
fmt.Println("Left operand:", node.Args[pos-1])
fmt.Println("Right operand:", node.Args[pos+1])
}
if !funcExists {
pos++
}
if dev.TemplateDebug {
fmt.Println("pos:", pos)
fmt.Println("len(node.Args):", len(node.Args))
}
return pos, out
}
func (c *CTemplateSet) compileIdentswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string, val reflect.Value) { func (c *CTemplateSet) compileIdentswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string, val reflect.Value) {
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("in compileIdentswitch") fmt.Println("in compileIdentswitch")
@ -514,200 +583,50 @@ ArgLoop:
case "not": case "not":
out += "!" out += "!"
case "or": case "or":
if dev.TemplateDebug { var rout string
fmt.Println("Building or function") pos, rout = c.compareJoin(varholder, holdreflect, templateName, pos, node, "||") // TODO: Test this
} out += rout
if pos == 0 {
fmt.Println("pos:", pos)
panic("or is missing a left operand")
}
if len(node.Args) <= pos {
fmt.Println("post pos:", pos)
fmt.Println("len(node.Args):", len(node.Args))
panic("or is missing a right operand")
}
left := c.compileBoolsub(node.Args[pos-1].String(), varholder, templateName, holdreflect)
_, funcExists := c.funcMap[node.Args[pos+1].String()]
var right string
if !funcExists {
right = c.compileBoolsub(node.Args[pos+1].String(), varholder, templateName, holdreflect)
}
out += left + " || " + right
if dev.TemplateDebug {
fmt.Println("Left operand:", node.Args[pos-1])
fmt.Println("Right operand:", node.Args[pos+1])
}
if !funcExists {
pos++
}
if dev.TemplateDebug {
fmt.Println("pos:", pos)
fmt.Println("len(node.Args):", len(node.Args))
}
case "and": case "and":
if dev.TemplateDebug { var rout string
fmt.Println("Building and function") pos, rout = c.compareJoin(varholder, holdreflect, templateName, pos, node, "&&") // TODO: Test this
} out += rout
if pos == 0 { case "le": // TODO: Can we condense these comparison cases down into one?
fmt.Println("pos:", pos) out += c.compareFunc(varholder, holdreflect, templateName, pos, node, "<=")
panic("and is missing a left operand")
}
if len(node.Args) <= pos {
fmt.Println("post pos:", pos)
fmt.Println("len(node.Args):", len(node.Args))
panic("and is missing a right operand")
}
left := c.compileBoolsub(node.Args[pos-1].String(), varholder, templateName, holdreflect)
_, funcExists := c.funcMap[node.Args[pos+1].String()]
var right string
if !funcExists {
right = c.compileBoolsub(node.Args[pos+1].String(), varholder, templateName, holdreflect)
}
out += left + " && " + right
if dev.TemplateDebug {
fmt.Println("Left operand:", node.Args[pos-1])
fmt.Println("Right operand:", node.Args[pos+1])
}
if !funcExists {
pos++
}
if dev.TemplateDebug {
fmt.Println("pos:", pos)
fmt.Println("len(node.Args):", len(node.Args))
}
case "le":
out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " <= " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect)
if dev.TemplateDebug {
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "lt": case "lt":
out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " < " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += c.compareFunc(varholder, holdreflect, templateName, pos, node, "<")
if dev.TemplateDebug {
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "gt": case "gt":
out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " > " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += c.compareFunc(varholder, holdreflect, templateName, pos, node, ">")
if dev.TemplateDebug {
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "ge": case "ge":
out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " >= " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += c.compareFunc(varholder, holdreflect, templateName, pos, node, ">=")
if dev.TemplateDebug {
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "eq": case "eq":
out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " == " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += c.compareFunc(varholder, holdreflect, templateName, pos, node, "==")
if dev.TemplateDebug {
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "ne": case "ne":
out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " != " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += c.compareFunc(varholder, holdreflect, templateName, pos, node, "!=")
if dev.TemplateDebug {
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "add": case "add":
param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) rout, rval := c.simpleMath(varholder, holdreflect, templateName, pos, node, "+")
param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += rout
val = rval
if val2.IsValid() {
val = val2
} else if val3.IsValid() {
val = val3
} else {
numSample := 1
val = reflect.ValueOf(numSample)
}
out += param1 + " + " + param2
if dev.TemplateDebug {
fmt.Println("add")
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "subtract": case "subtract":
param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) rout, rval := c.simpleMath(varholder, holdreflect, templateName, pos, node, "-")
param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += rout
val = rval
if val2.IsValid() {
val = val2
} else if val3.IsValid() {
val = val3
} else {
numSample := 1
val = reflect.ValueOf(numSample)
}
out += param1 + " - " + param2
if dev.TemplateDebug {
fmt.Println("subtract")
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "divide": case "divide":
param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) rout, rval := c.simpleMath(varholder, holdreflect, templateName, pos, node, "/")
param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += rout
val = rval
if val2.IsValid() {
val = val2
} else if val3.IsValid() {
val = val3
} else {
numSample := 1
val = reflect.ValueOf(numSample)
}
out += param1 + " / " + param2
if dev.TemplateDebug {
fmt.Println("divide")
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
case "multiply": case "multiply":
param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) rout, rval := c.simpleMath(varholder, holdreflect, templateName, pos, node, "*")
param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) out += rout
val = rval
if val2.IsValid() {
val = val2
} else if val3.IsValid() {
val = val3
} else {
numSample := 1
val = reflect.ValueOf(numSample)
}
out += param1 + " * " + param2
if dev.TemplateDebug {
fmt.Println("multiply")
fmt.Println("node.Args[pos + 1]", node.Args[pos+1])
fmt.Println("node.Args[pos + 2]", node.Args[pos+2])
}
break ArgLoop break ArgLoop
default: default:
if dev.TemplateDebug { if dev.TemplateDebug {
@ -726,6 +645,7 @@ ArgLoop:
//for _, outval := range outbuf { //for _, outval := range outbuf {
// out += outval // out += outval
//} //}
//log.Print("outbit: ", out)
return out, val return out, val
} }
@ -747,7 +667,7 @@ func (c *CTemplateSet) compileReflectswitch(varholder string, holdreflect reflec
case *parse.ChainNode: case *parse.ChainNode:
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("Chain Node:", n.Node) fmt.Println("Chain Node:", n.Node)
fmt.Println("node.Args", node.Args) fmt.Println("node.Args:", node.Args)
} }
return "", outVal return "", outVal
case *parse.DotNode: case *parse.DotNode:
@ -835,7 +755,6 @@ func (c *CTemplateSet) compileIfVarsub(varname string, varholder string, templat
} else { } else {
out += "." + bit out += "." + bit
} }
if !cur.IsValid() { if !cur.IsValid() {
panic(out + "^\n" + "Invalid value. Maybe, it doesn't exist?") panic(out + "^\n" + "Invalid value. Maybe, it doesn't exist?")
} }

View File

@ -699,6 +699,27 @@ select, input, textarea {
margin-right: 10px; margin-right: 10px;
} }
#profile_container, #profile_left_pane {
display: flex;
}
#profile_left_lane {
border: 1px solid var(--element-border-color);
border-bottom: 2px solid var(--element-border-color);
}
#profile_left_pane {
flex-direction: column;
}
#profile_left_pane .avatarRow {
padding: 24px;
}
#profile_left_pane .avatar {
border-radius: 80px;
}
#profile_right_lane .colstack_item {
border: 1px solid var(--element-border-color);
border-bottom: 2px solid var(--element-border-color);
}
@media(max-width: 670px) { @media(max-width: 670px) {
.topic_inner_right { .topic_inner_right {
display: none; display: none;

View File

@ -58,6 +58,7 @@ type MemoryTopicStore struct {
get *sql.Stmt get *sql.Stmt
exists *sql.Stmt exists *sql.Stmt
topicCount *sql.Stmt topicCount *sql.Stmt
create *sql.Stmt
sync.RWMutex sync.RWMutex
} }
@ -70,6 +71,7 @@ func NewMemoryTopicStore(capacity int) (*MemoryTopicStore, error) {
get: acc.SimpleSelect("topics", "title, content, createdBy, createdAt, lastReplyAt, is_closed, sticky, parentID, ipaddress, postCount, likeCount, data", "tid = ?", "", ""), get: acc.SimpleSelect("topics", "title, content, createdBy, createdAt, lastReplyAt, is_closed, sticky, parentID, ipaddress, postCount, likeCount, data", "tid = ?", "", ""),
exists: acc.SimpleSelect("topics", "tid", "tid = ?", "", ""), exists: acc.SimpleSelect("topics", "tid", "tid = ?", "", ""),
topicCount: acc.SimpleCount("topics", "", ""), topicCount: acc.SimpleCount("topics", "", ""),
create: acc.SimpleInsert("topics", "parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?"),
}, acc.FirstError() }, acc.FirstError()
} }
@ -146,7 +148,7 @@ func (mts *MemoryTopicStore) Create(fid int, topicName string, content string, u
wcount := wordCount(content) wcount := wordCount(content)
// TODO: Move this statement into the topic store // TODO: Move this statement into the topic store
res, err := stmts.createTopic.Exec(fid, topicName, content, parsedContent, uid, ipaddress, wcount, uid) res, err := mts.create.Exec(fid, topicName, content, parsedContent, uid, ipaddress, wcount, uid)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -253,6 +255,7 @@ type SQLTopicStore struct {
get *sql.Stmt get *sql.Stmt
exists *sql.Stmt exists *sql.Stmt
topicCount *sql.Stmt topicCount *sql.Stmt
create *sql.Stmt
} }
func NewSQLTopicStore() (*SQLTopicStore, error) { func NewSQLTopicStore() (*SQLTopicStore, error) {
@ -261,6 +264,7 @@ func NewSQLTopicStore() (*SQLTopicStore, error) {
get: acc.SimpleSelect("topics", "title, content, createdBy, createdAt, lastReplyAt, is_closed, sticky, parentID, ipaddress, postCount, likeCount, data", "tid = ?", "", ""), get: acc.SimpleSelect("topics", "title, content, createdBy, createdAt, lastReplyAt, is_closed, sticky, parentID, ipaddress, postCount, likeCount, data", "tid = ?", "", ""),
exists: acc.SimpleSelect("topics", "tid", "tid = ?", "", ""), exists: acc.SimpleSelect("topics", "tid", "tid = ?", "", ""),
topicCount: acc.SimpleCount("topics", "", ""), topicCount: acc.SimpleCount("topics", "", ""),
create: acc.SimpleInsert("topics", "parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?"),
}, acc.FirstError() }, acc.FirstError()
} }
@ -297,7 +301,7 @@ func (sts *SQLTopicStore) Create(fid int, topicName string, content string, uid
wcount := wordCount(content) wcount := wordCount(content)
// TODO: Move this statement into the topic store // TODO: Move this statement into the topic store
res, err := stmts.createTopic.Exec(fid, topicName, content, parsedContent, uid, ipaddress, wcount, uid) res, err := sts.create.Exec(fid, topicName, content, parsedContent, uid, ipaddress, wcount, uid)
if err != nil { if err != nil {
return 0, err return 0, err
} }