dict @ ea26916be0ea693b6aefc46f3eeb62e44b8d7cb0

feat: Add barebones tcp server
  1diff --git a/cmd/dict/main.go b/cmd/dict/main.go
  2index 09e9412599a4f1d86d1348570f7abec66e36fd6c..5bd60961e253fce4164294ee8db575dbec452b89 100644
  3--- a/cmd/dict/main.go
  4+++ b/cmd/dict/main.go
  5@@ -7,6 +7,7 @@
  6 	"github.com/urfave/cli/v2"
  7 
  8 	"git.gabrielgio.me/dict/cmd/importer"
  9+	"git.gabrielgio.me/dict/cmd/server"
 10 	"git.gabrielgio.me/dict/cmd/ui"
 11 )
 12 
 13@@ -17,6 +18,7 @@ 		Usage: "interactive dictionary",
 14 		Commands: []*cli.Command{
 15 			importer.ImportCommand,
 16 			ui.UICommand,
 17+			server.ServeCommand,
 18 		},
 19 	}
 20 
 21diff --git a/cmd/server/server.go b/cmd/server/server.go
 22new file mode 100644
 23index 0000000000000000000000000000000000000000..a0de54712bf0f32a79e990fee1ceab4796f21abf
 24--- /dev/null
 25+++ b/cmd/server/server.go
 26@@ -0,0 +1,96 @@
 27+package server
 28+
 29+import (
 30+	"context"
 31+	"fmt"
 32+	"io"
 33+	"log/slog"
 34+	"net"
 35+	"strings"
 36+
 37+	"git.gabrielgio.me/dict/db"
 38+	"github.com/urfave/cli/v2"
 39+)
 40+
 41+var ServeCommand = &cli.Command{
 42+	Name:  "serve",
 43+	Usage: "Start a simple tcp server to ansower queries",
 44+	Flags: []cli.Flag{
 45+		&cli.StringFlag{
 46+			Name:  "addr",
 47+			Value: "/tmp/dict.sock",
 48+			Usage: "Address",
 49+		},
 50+		&cli.StringFlag{
 51+			Name:  "database",
 52+			Value: "main.dict",
 53+			Usage: "Dictionary database location",
 54+		},
 55+	},
 56+	Action: func(cCtx *cli.Context) error {
 57+		addr := cCtx.String("addr")
 58+		database := cCtx.String("database")
 59+		return Server(context.Background(), addr, database)
 60+	},
 61+}
 62+
 63+func Server(ctx context.Context, addr, database string) error {
 64+	// Listen for incoming connections on port 8080
 65+	db, err := db.Open(database)
 66+	if err != nil {
 67+		return fmt.Errorf("Error openning datbase:%w", err)
 68+	}
 69+
 70+	ln, err := net.Listen("unix", addr)
 71+	if err != nil {
 72+		return err
 73+	}
 74+
 75+	defer ln.Close()
 76+
 77+	// Accept incoming connections and handle them
 78+	for {
 79+		conn, err := ln.Accept()
 80+		if err != nil {
 81+			slog.Error("Error accepting conn", "error", err)
 82+			continue
 83+		}
 84+
 85+		slog.Info("Connection accepeted")
 86+		go handleConnection(conn, db)
 87+	}
 88+}
 89+
 90+func handleConnection(conn net.Conn, db *db.DB) {
 91+	defer conn.Close()
 92+
 93+	// Read incoming data
 94+	buf := make([]byte, 0, 4096) // big buffer
 95+	tmp := make([]byte, 256)     // using small tmo buffer for demonstrating
 96+	for {
 97+		n, err := conn.Read(tmp)
 98+		if err != nil {
 99+			if err != io.EOF {
100+				slog.Error("Error reading conn", "error", err)
101+				return
102+			}
103+			break
104+		}
105+		buf = append(buf, tmp[:n]...)
106+
107+	}
108+
109+	q := strings.ReplaceAll(string(buf), "\n", "")
110+
111+	slog.Info("Query", "query", q)
112+	ws, err := db.SelectDict(context.Background(), q, 10)
113+	if err != nil {
114+		slog.Error("Error selecting", "error", err)
115+		return
116+	}
117+
118+	slog.Info("Count", "q", len(ws))
119+	for _, w := range ws {
120+		fmt.Fprintf(conn, "%s\n%s\n\n", w.Word, w.Line)
121+	}
122+}
123diff --git a/db/db.go b/db/db.go
124index b28dea2cb1aa9b02df7b1ab68295f21e6f36458e..61f3bb5c2d8240e651ca80c8ff127201c7b965bc 100644
125--- a/db/db.go
126+++ b/db/db.go
127@@ -56,7 +56,8 @@ 		`SELECT
128 			word, line
129 		FROM words
130 		WHERE word MATCH ?
131-		ORDER BY rank;`,
132+		ORDER BY rank
133+		LIMIT ?;`,
134 		query, limit,
135 	)
136 	if err != nil {