package grid import ( "fmt" "strings" ) // Cell represents a single cell in the grid. type Cell struct { R rune // Color } // Grid is the struct holding the grid information. type Grid struct { Cells []Cell Width int Height int Label string } // FromRunes creates a new grid from a rune slice. func FromRunes(runes []rune, width, height int) Grid { g := Grid{ Width: width, Height: height, } g.Cells = make([]Cell, len(runes)) for i, r := range runes { g.Cells[i].R = r } return g } // TODO: Grow. // TODO: Shrink. // TODO: Cellmap for prettyprints. // FromRunes reads in cells from a rune-slice. // NOTE: Does not update width/height. func (g *Grid) FromRunes(runes []rune) { g.Cells = make([]Cell, len(runes)) for i, r := range runes { g.Cells[i].R = r } } // Clone returns a deep copy of the grid. func (g *Grid) Clone() *Grid { clone := Grid{ Cells: make([]Cell, len(g.Cells)), Width: g.Width, Height: g.Height, Label: g.Label, } copy(clone.Cells, g.Cells) return &clone } // Set sets a cell at location. func (g *Grid) Set(x, y int, c Cell) { g.Cells[(y*g.Width)+x] = c } // Get gets a cell at location. func (g *Grid) Get(x, y int) Cell { return g.Cells[(y*g.Width)+x] } func (g Grid) String() string { var result strings.Builder result.Grow((g.Width * g.Height) * 2) fmt.Fprintf(&result, "╭") fmt.Fprintf(&result, "─ %s ─", g.Label) for x := len(g.Label) + 4; x < g.Width+2; x++ { fmt.Fprintf(&result, "─") } fmt.Fprintf(&result, "╮\n") for y := 0; y < g.Height; y++ { fmt.Fprintf(&result, "│ ") i := y * g.Width for x := 0; x < g.Width; x++ { r := g.Cells[i+x].R if r < ' ' { r = ' ' } fmt.Fprintf(&result, "%c", r) } fmt.Fprintf(&result, " │\n") } fmt.Fprintf(&result, "╰") for x := 1; x < g.Width+3; x++ { fmt.Fprintf(&result, "─") } fmt.Fprintf(&result, "╯") return result.String() }