Function bodies 52 total
startBlocker function · go · L11-L29 (19 LOC)blocker.go
func startBlocker(apps []string, paused *atomic.Bool, stop chan struct{}) tea.Cmd {
return func() tea.Msg {
killApps(apps)
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-stop:
return blockerStoppedMsg{}
case <-ticker.C:
if !paused.Load() {
killApps(apps)
}
}
}
}
}killApps function · go · L31-L35 (5 LOC)blocker.go
func killApps(apps []string) {
for _, app := range apps {
_ = exec.Command("pkill", "-x", app).Run()
}
}timerColor method · go · L28-L38 (11 LOC)colors.go
func (m model) timerColor() lipgloss.Color {
frac := float64(m.remaining) / float64(m.totalDuration)
switch {
case frac <= 0.10:
return colorRed
case frac <= 0.25:
return colorYellow
default:
return colorGreen
}
}init function · go · L19-L48 (30 LOC)fonts.go
func init() {
for _, f := range fonts {
// Find max rune width across digit glyphs (skip ':')
maxWidth := 0
for ch, rows := range f.digits {
if ch == ':' {
continue
}
for _, row := range rows {
if w := utf8.RuneCountInString(row); w > maxWidth {
maxWidth = w
}
}
}
// Center-pad each digit row to maxWidth
for ch, rows := range f.digits {
if ch == ':' {
continue
}
for i, row := range rows {
w := utf8.RuneCountInString(row)
if w < maxWidth {
left := (maxWidth - w) / 2
right := maxWidth - w - left
rows[i] = strings.Repeat(" ", left) + row + strings.Repeat(" ", right)
}
}
}
}
}renderDigit function · go · L50-L56 (7 LOC)fonts.go
func renderDigit(f *fontData, ch rune) string {
rows, ok := f.digits[ch]
if !ok {
return string(ch)
}
return strings.Join(rows, "\n")
}fontSpacer function · go · L58-L64 (7 LOC)fonts.go
func fontSpacer(height int) string {
rows := make([]string, height)
for i := range rows {
rows[i] = " "
}
return strings.Join(rows, "\n")
}parseArgs function · go · L22-L99 (78 LOC)main.go
func parseArgs(args []string) config {
if len(args) == 0 {
printUsage()
os.Exit(1)
}
var cfg config
var positional []string
for i := 0; i < len(args); i++ {
switch args[i] {
case "-h", "--help":
printUsage()
os.Exit(0)
case "--block":
if i+1 >= len(args) {
fmt.Fprintln(os.Stderr, "error: --block requires an argument")
os.Exit(1)
}
i++
cfg.blockApps = strings.Split(args[i], ",")
case "--viz":
if i+1 >= len(args) {
fmt.Fprintln(os.Stderr, "error: --viz requires an argument")
os.Exit(1)
}
i++
switch args[i] {
case "bar", "defrag", "binary", "bubble", "merge", "quick":
cfg.vizMode = args[i]
default:
fmt.Fprintf(os.Stderr, "error: unknown viz mode %q (use bar, defrag, binary, bubble, merge, or quick)\n", args[i])
os.Exit(1)
}
case "--font":
if i+1 >= len(args) {
fmt.Fprintln(os.Stderr, "error: --font requires an argument")
os.Exit(1)
}
i++
switch args[i] {
case "block", "slim", "doAbout: code-quality intelligence by Repobility · https://repobility.com
printUsage function · go · L101-L117 (17 LOC)main.go
func printUsage() {
fmt.Fprintln(os.Stderr, `Usage: lockin <duration> [task name] [flags]
Duration formats: 30s, 5m, 30m, 1h, 1h30m
Flags:
--block App1,App2 Block apps while timer runs
--viz bar|defrag|binary|bubble|merge|quick
Visualization mode
--font block|slim|dot Timer font style
Examples:
lockin 30m "deep work"
lockin 25m --block Safari,Messages,Discord
lockin 1h30m --viz defrag
lockin 25m --font slim --viz binary`)
}listenSIGUSR1 function · go · L119-L125 (7 LOC)main.go
func listenSIGUSR1(p *tea.Program) {
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGUSR1)
for range sig {
p.Send(togglePauseMsg{})
}
}main function · go · L127-L147 (21 LOC)main.go
func main() {
cfg := parseArgs(os.Args[1:])
m := newModel(cfg)
p := tea.NewProgram(m, tea.WithAltScreen())
go listenSIGUSR1(p)
finalModel, err := p.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
if fm, ok := finalModel.(model); ok && fm.remaining <= 0 {
fmt.Printf("lockin: %s complete", cfg.duration)
if cfg.taskName != "" {
fmt.Printf(" — %s", cfg.taskName)
}
fmt.Println()
}
}newModel function · go · L51-L66 (16 LOC)model.go
func newModel(cfg config) model {
m := model{
totalDuration: cfg.duration,
remaining: cfg.duration,
taskName: cfg.taskName,
blockApps: cfg.blockApps,
vizMode: cfg.vizMode,
font: fonts[cfg.fontStyle],
blockerStop: make(chan struct{}),
blockerPaused: &atomic.Bool{},
}
if m.isDotFont() {
m.updateDotFade()
}
return m
}doTick function · go · L71-L75 (5 LOC)model.go
func doTick() tea.Cmd {
return tea.Tick(time.Second, func(t time.Time) tea.Msg {
return tickMsg(t)
})
}doVizTick function · go · L77-L81 (5 LOC)model.go
func doVizTick() tea.Cmd {
return tea.Tick(100*time.Millisecond, func(t time.Time) tea.Msg {
return vizTickMsg{}
})
}needsFastTick method · go · L83-L92 (10 LOC)model.go
func (m model) needsFastTick() bool {
if m.isDotFont() {
return true
}
switch m.vizMode {
case "bar", "binary", "bubble", "merge", "quick":
return true
}
return false
}Init method · go · L94-L103 (10 LOC)model.go
func (m model) Init() tea.Cmd {
cmds := []tea.Cmd{doTick()}
if len(m.blockApps) > 0 {
cmds = append(cmds, startBlocker(m.blockApps, m.blockerPaused, m.blockerStop))
}
if m.needsFastTick() {
cmds = append(cmds, doVizTick())
}
return tea.Batch(cmds...)
}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
Update method · go · L105-L183 (79 LOC)model.go
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width = msg.Width
m.height = msg.Height
if m.vizMode == "defrag" {
m.initDefragGrid()
}
if m.vizMode == "bubble" || m.vizMode == "merge" || m.vizMode == "quick" {
m.initSortGrid()
}
return m, nil
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
m.done = true
m.shutdown()
return m, tea.Quit
case " ":
m.paused = !m.paused
m.blockerPaused.Store(m.paused)
if !m.paused && m.needsFastTick() {
m.lastTickAt = time.Now()
return m, doVizTick()
}
return m, nil
}
return m, nil
case togglePauseMsg:
m.paused = !m.paused
m.blockerPaused.Store(m.paused)
if !m.paused && m.needsFastTick() {
m.lastTickAt = time.Now()
return m, doVizTick()
}
return m, nil
case vizTickMsg:
if m.paused || m.done {
return m, nil
}
return m, doVizTick()
case tickMsg:
if m.paused || m.done {
return m, doTicshutdown method · go · L185-L191 (7 LOC)model.go
func (m *model) shutdown() {
select {
case <-m.blockerStop:
default:
close(m.blockerStop)
}
}View method · go · L193-L238 (46 LOC)model.go
func (m model) View() string {
if m.done {
return ""
}
var sections []string
// Task name
if m.taskName != "" {
style := lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("7"))
sections = append(sections, style.Render(m.taskName))
}
// Spacer
sections = append(sections, "")
// Big timer digits
sections = append(sections, m.renderBigTimer())
// Pause indicator
if m.paused {
style := lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("11"))
sections = append(sections, "")
sections = append(sections, style.Render("PAUSED"))
}
// Visualization
if m.vizMode != "" {
sections = append(sections, "")
sections = append(sections, m.renderViz())
}
// Blocked apps
if len(m.blockApps) > 0 {
sections = append(sections, "")
sections = append(sections, m.renderBlockedApps())
}
body := lipgloss.JoinVertical(lipgloss.Center, sections...)
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, body)
}timerTimeStr method · go · L245-L253 (9 LOC)model.go
func (m model) timerTimeStr() string {
h := int(m.remaining.Hours())
min := int(m.remaining.Minutes()) % 60
sec := int(m.remaining.Seconds()) % 60
if h > 0 {
return fmt.Sprintf("%d:%02d:%02d", h, min, sec)
}
return fmt.Sprintf("%02d:%02d", min, sec)
}timerCols method · go · L259-L278 (20 LOC)model.go
func (m model) timerCols() []glyphCol {
timeStr := m.timerTimeStr()
var cols []glyphCol
for i, ch := range timeStr {
if rows, ok := m.font.digits[ch]; ok {
cols = append(cols, glyphCol{rows})
}
if i < len(timeStr)-1 {
nextCh := rune(timeStr[i+1])
if ch != ':' && nextCh != ':' {
spacerRows := make([]string, m.font.height)
for j := range spacerRows {
spacerRows[j] = " "
}
cols = append(cols, glyphCol{spacerRows})
}
}
}
return cols
}buildTimerGrid method · go · L280-L291 (12 LOC)model.go
func (m model) buildTimerGrid() [][]rune {
cols := m.timerCols()
var grid [][]rune
for row := 0; row < m.font.height; row++ {
var rowRunes []rune
for _, c := range cols {
rowRunes = append(rowRunes, []rune(c.rows[row])...)
}
grid = append(grid, rowRunes)
}
return grid
}updateDotFade method · go · L293-L334 (42 LOC)model.go
func (m *model) updateDotFade() {
grid := m.buildTimerGrid()
if len(grid) == 0 {
return
}
width := len(grid[0])
total := m.font.height * width
currentCells := make([]bool, total)
for r, row := range grid {
for c, ch := range row {
if ch != ' ' {
currentCells[r*width+c] = true
}
}
}
if len(m.dotPrevCells) != total {
m.dotPrevCells = currentCells
m.dotOnAt = make([]time.Time, total)
m.dotOffAt = make([]time.Time, total)
now := time.Now()
for i, on := range currentCells {
if on {
m.dotOnAt[i] = now
}
}
return
}
now := time.Now()
for i := range currentCells {
if !m.dotPrevCells[i] && currentCells[i] {
m.dotOnAt[i] = now
}
if m.dotPrevCells[i] && !currentCells[i] {
m.dotOffAt[i] = now
}
}
m.dotPrevCells = currentCells
}renderBigTimer method · go · L336-L452 (117 LOC)model.go
func (m model) renderBigTimer() string {
baseColor := m.timerColor()
cols := m.timerCols()
isBlock := m.isBlockFont()
isDot := m.isDotFont()
if !isBlock && !isDot {
// Default path: per-row gradient (slim font, etc.)
var renderedRows []string
for row := 0; row < m.font.height; row++ {
color := shaderGradient(row, 0, m.font.height, len(cols), baseColor, 0)
style := lipgloss.NewStyle().Foreground(color)
var rowStr strings.Builder
for _, c := range cols {
rowStr.WriteString(style.Render(c.rows[row]))
}
renderedRows = append(renderedRows, rowStr.String())
}
return strings.Join(renderedRows, "\n")
}
// Build 2D rune grid for per-cell rendering
var grid [][]rune
for row := 0; row < m.font.height; row++ {
var rowRunes []rune
for _, c := range cols {
rowRunes = append(rowRunes, []rune(c.rows[row])...)
}
grid = append(grid, rowRunes)
}
if len(grid) == 0 {
return ""
}
gridWidth := len(grid[0])
renderHeight := m.font.height
if isBlocOpen data scored by Repobility · https://repobility.com
renderBlockedApps method · go · L454-L462 (9 LOC)model.go
func (m model) renderBlockedApps() string {
var parts []string
for _, app := range m.blockApps {
parts = append(parts, "🔒 "+app)
}
style := lipgloss.NewStyle().
Foreground(colorDim)
return style.Render(strings.Join(parts, " "))
}clamp01 function · go · L18-L26 (9 LOC)shaders.go
func clamp01(v float64) float64 {
if v < 0 {
return 0
}
if v > 1 {
return 1
}
return v
}hexToRGB function · go · L28-L35 (8 LOC)shaders.go
func hexToRGB(hex string) (uint8, uint8, uint8) {
var r, g, b uint8
if len(hex) > 0 && hex[0] == '#' {
hex = hex[1:]
}
fmt.Sscanf(hex, "%02x%02x%02x", &r, &g, &b)
return r, g, b
}rgbToHex function · go · L37-L39 (3 LOC)shaders.go
func rgbToHex(r, g, b uint8) string {
return fmt.Sprintf("#%02x%02x%02x", r, g, b)
}rgbToHSL function · go · L41-L78 (38 LOC)shaders.go
func rgbToHSL(r, g, b uint8) hsl {
rf := float64(r) / 255.0
gf := float64(g) / 255.0
bf := float64(b) / 255.0
max := math.Max(rf, math.Max(gf, bf))
min := math.Min(rf, math.Min(gf, bf))
l := (max + min) / 2.0
if max == min {
return hsl{0, 0, l}
}
d := max - min
var s float64
if l > 0.5 {
s = d / (2.0 - max - min)
} else {
s = d / (max + min)
}
var h float64
switch max {
case rf:
h = (gf - bf) / d
if gf < bf {
h += 6
}
case gf:
h = (bf-rf)/d + 2
case bf:
h = (rf-gf)/d + 4
}
h /= 6
return hsl{h, s, l}
}hueToRGB function · go · L80-L97 (18 LOC)shaders.go
func hueToRGB(p, q, t float64) float64 {
if t < 0 {
t += 1
}
if t > 1 {
t -= 1
}
if t < 1.0/6.0 {
return p + (q-p)*6*t
}
if t < 1.0/2.0 {
return q
}
if t < 2.0/3.0 {
return p + (q-p)*(2.0/3.0-t)*6
}
return p
}hslToRGB function · go · L99-L118 (20 LOC)shaders.go
func hslToRGB(c hsl) (uint8, uint8, uint8) {
if c.s == 0 {
v := uint8(clamp01(c.l) * 255)
return v, v, v
}
var q float64
if c.l < 0.5 {
q = c.l * (1 + c.s)
} else {
q = c.l + c.s - c.l*c.s
}
p := 2*c.l - q
r := uint8(clamp01(hueToRGB(p, q, c.h+1.0/3.0)) * 255)
g := uint8(clamp01(hueToRGB(p, q, c.h)) * 255)
b := uint8(clamp01(hueToRGB(p, q, c.h-1.0/3.0)) * 255)
return r, g, b
}modifyColor function · go · L120-L134 (15 LOC)shaders.go
func modifyColor(base lipgloss.Color, fn func(hsl) hsl) lipgloss.Color {
hex := string(base)
if len(hex) > 0 && hex[0] != '#' {
if h, ok := ansiToHex[hex]; ok {
hex = h
}
}
r, g, b := hexToRGB(hex)
c := rgbToHSL(r, g, b)
c = fn(c)
c.l = clamp01(c.l)
c.s = clamp01(c.s)
nr, ng, nb := hslToRGB(c)
return lipgloss.Color(rgbToHex(nr, ng, nb))
}Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
shaderGradient function · go · L137-L146 (10 LOC)shaders.go
func shaderGradient(row, col, height, cols int, base lipgloss.Color, t float64) lipgloss.Color {
if height <= 1 {
return base
}
frac := float64(row) / float64(height-1) // 0 at top, 1 at bottom
return modifyColor(base, func(c hsl) hsl {
c.l = clamp01(c.l * (1.15 - frac*0.65))
return c
})
}progressFraction method · go · L13-L28 (16 LOC)viz.go
func (m model) progressFraction() float64 {
if m.totalDuration == 0 {
return 0
}
elapsed := m.totalDuration - m.remaining
// Interpolate sub-second progress using wall clock
if !m.paused && !m.done && !m.lastTickAt.IsZero() {
elapsed += time.Since(m.lastTickAt)
}
// Finish viz with 10% of time remaining so the completed state is visible
frac := float64(elapsed) / (float64(m.totalDuration) * 0.9)
if frac > 1 {
frac = 1
}
return frac
}neonPulse function · go · L31-L37 (7 LOC)viz.go
func neonPulse(width float64) (pos, pulseWidth float64) {
const period = 2.0 // seconds per sweep
t := math.Mod(float64(time.Now().UnixMilli())/1000.0, period) / period
pos = t * width
pulseWidth = math.Max(width*0.05, 1.0)
return
}pulseBoost function · go · L39-L42 (4 LOC)viz.go
func pulseBoost(x, pulsePos, pulseWidth float64) float64 {
dist := math.Abs(x - pulsePos)
return math.Exp(-(dist * dist) / (2 * pulseWidth * pulseWidth))
}renderViz method · go · L44-L57 (14 LOC)viz.go
func (m model) renderViz() string {
switch m.vizMode {
case "bar":
return m.renderBar()
case "defrag":
return m.renderDefrag()
case "binary":
return m.renderBinary()
case "bubble", "merge", "quick":
return m.renderSort()
default:
return ""
}
}renderBar method · go · L61-L102 (42 LOC)viz.go
func (m model) renderBar() string {
maxWidth := 60
if m.width-4 < maxWidth {
maxWidth = m.width - 4
}
if maxWidth < 10 {
maxWidth = 10
}
frac := m.progressFraction()
filled := int(frac * float64(maxWidth))
if filled > maxWidth {
filled = maxWidth
}
baseColor := m.timerColor()
pulsePos, pulseW := neonPulse(float64(maxWidth))
var bar strings.Builder
for i := 0; i < maxWidth; i++ {
boost := pulseBoost(float64(i), pulsePos, pulseW)
var base lipgloss.Color
var ch string
if i < filled {
base = baseColor
ch = "█"
} else {
base = colorDim
ch = "░"
}
color := modifyColor(base, func(c hsl) hsl {
c.l = clamp01(c.l + boost*0.35)
return c
})
bar.WriteString(lipgloss.NewStyle().Foreground(color).Render(ch))
}
pct := fmt.Sprintf(" %d%%", int(frac*100))
pctStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("7"))
return bar.String() + pctStyle.Render(pct)
}initDefragGrid method · go · L106-L127 (22 LOC)viz.go
func (m *model) initDefragGrid() {
w := m.defragGridWidth()
h := 8
total := w * h
if m.defragWidth == w && len(m.defragOriginal) == total {
return
}
m.defragWidth = w
m.defragOriginal = make([]uint8, total)
// Fill ~65% of cells with data, rest free
dataCount := total * 65 / 100
for i := 0; i < dataCount; i++ {
m.defragOriginal[i] = 1
}
// Shuffle to create chaotic layout
rand.Shuffle(total, func(i, j int) {
m.defragOriginal[i], m.defragOriginal[j] = m.defragOriginal[j], m.defragOriginal[i]
})
}defragGridWidth method · go · L129-L137 (9 LOC)viz.go
func (m model) defragGridWidth() int {
w := m.width * 6 / 10
if w < 10 {
w = 10
}
// Each cell renders as 2 chars (██ or ░░), so halve the available width
w = w / 2
return w
}About: code-quality intelligence by Repobility · https://repobility.com
renderDefrag method · go · L139-L187 (49 LOC)viz.go
func (m model) renderDefrag() string {
if len(m.defragOriginal) == 0 || m.defragWidth == 0 {
return ""
}
total := len(m.defragOriginal)
frac := m.progressFraction()
cursor := int(frac * float64(total))
if cursor > total {
cursor = total
}
// Count data cells in the processed region (0..cursor)
dataInProcessed := 0
for i := 0; i < cursor; i++ {
if m.defragOriginal[i] == 1 {
dataInProcessed++
}
}
dataStyle := lipgloss.NewStyle().Foreground(colorDefragData)
fragStyle := lipgloss.NewStyle().Foreground(colorDefragFrag)
freeStyle := lipgloss.NewStyle().Foreground(colorDefragFree)
var rows []string
for rowStart := 0; rowStart < total; rowStart += m.defragWidth {
end := rowStart + m.defragWidth
if end > total {
end = total
}
var row strings.Builder
for i := rowStart; i < end; i++ {
if i < dataInProcessed {
row.WriteString(dataStyle.Render("██"))
} else if i < cursor {
row.WriteString(freeStyle.Render("░░"))
} else {
if m.defragOrrainbowColor function · go · L191-L193 (3 LOC)viz.go
func rainbowColor(value, total int) lipgloss.Color {
return rainbowColorL(value, total, 0.5)
}rainbowColorL function · go · L195-L199 (5 LOC)viz.go
func rainbowColorL(value, total int, lightness float64) lipgloss.Color {
h := float64(value) / float64(total) * 0.85 // stop before wrapping back to red
r, g, b := hslToRGB(hsl{h, 1.0, lightness})
return lipgloss.Color(rgbToHex(r, g, b))
}initSortGrid method · go · L201-L241 (41 LOC)viz.go
func (m *model) initSortGrid() {
w := m.defragGridWidth()
h := 4
total := w * h
if m.sortWidth == w && len(m.sortFrames) > 0 {
return
}
m.sortWidth = w
arr := make([]int, total)
for i := range arr {
arr[i] = i
}
rand.Shuffle(total, func(i, j int) {
arr[i], arr[j] = arr[j], arr[i]
})
var frames [][]int
switch m.vizMode {
case "bubble":
frames = bubbleSortFrames(arr)
case "merge":
frames = mergeSortFrames(arr)
case "quick":
frames = quickSortFrames(arr)
}
// Subsample to cap memory usage
const maxFrames = 2000
if len(frames) <= maxFrames {
m.sortFrames = frames
return
}
subsampled := make([][]int, maxFrames)
for i := range subsampled {
subsampled[i] = frames[i*(len(frames)-1)/(maxFrames-1)]
}
m.sortFrames = subsampled
}renderSort method · go · L243-L294 (52 LOC)viz.go
func (m model) renderSort() string {
if len(m.sortFrames) == 0 || m.sortWidth == 0 {
return ""
}
frac := m.progressFraction()
idx := int(frac * float64(len(m.sortFrames)-1))
if idx >= len(m.sortFrames) {
idx = len(m.sortFrames) - 1
}
frame := m.sortFrames[idx]
total := len(frame)
// Glow map: find most recent change per cell, decay over trail
const trailLen = 8
glow := make([]float64, total)
for i := range frame {
for j := idx; j > idx-trailLen && j > 0; j-- {
if m.sortFrames[j][i] != m.sortFrames[j-1][i] {
glow[i] = 1.0 - float64(idx-j)/float64(trailLen)
break
}
}
}
var rows []string
for rowStart := 0; rowStart < total; rowStart += m.sortWidth {
end := rowStart + m.sortWidth
if end > total {
end = total
}
var row strings.Builder
for i := rowStart; i < end; i++ {
// Snap glow to 3 discrete lightness levels (no modifyColor)
var l float64
switch {
case glow[i] > 0.66:
l = 0.7
case glow[i] > 0.33:
l = 0.5
defabubbleSortFrames function · go · L296-L311 (16 LOC)viz.go
func bubbleSortFrames(arr []int) [][]int {
a := make([]int, len(arr))
copy(a, arr)
frames := [][]int{append([]int(nil), a...)}
n := len(a)
for i := 0; i < n-1; i++ {
for j := 0; j < n-1-i; j++ {
if a[j] > a[j+1] {
a[j], a[j+1] = a[j+1], a[j]
frames = append(frames, append([]int(nil), a...))
}
}
}
return frames
}mergeSortFrames function · go · L313-L320 (8 LOC)viz.go
func mergeSortFrames(arr []int) [][]int {
a := make([]int, len(arr))
copy(a, arr)
frames := [][]int{append([]int(nil), a...)}
mergeSortRec(a, 0, len(a), &frames)
return frames
}mergeSortRec function · go · L322-L330 (9 LOC)viz.go
func mergeSortRec(a []int, lo, hi int, frames *[][]int) {
if hi-lo <= 1 {
return
}
mid := (lo + hi) / 2
mergeSortRec(a, lo, mid, frames)
mergeSortRec(a, mid, hi, frames)
mergeHalves(a, lo, mid, hi, frames)
}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
mergeHalves function · go · L332-L362 (31 LOC)viz.go
func mergeHalves(a []int, lo, mid, hi int, frames *[][]int) {
left := make([]int, mid-lo)
right := make([]int, hi-mid)
copy(left, a[lo:mid])
copy(right, a[mid:hi])
i, j, k := 0, 0, lo
for i < len(left) && j < len(right) {
if left[i] <= right[j] {
a[k] = left[i]
i++
} else {
a[k] = right[j]
j++
}
k++
*frames = append(*frames, append([]int(nil), a...))
}
for i < len(left) {
a[k] = left[i]
i++
k++
*frames = append(*frames, append([]int(nil), a...))
}
for j < len(right) {
a[k] = right[j]
j++
k++
*frames = append(*frames, append([]int(nil), a...))
}
}quickSortFrames function · go · L364-L371 (8 LOC)viz.go
func quickSortFrames(arr []int) [][]int {
a := make([]int, len(arr))
copy(a, arr)
frames := [][]int{append([]int(nil), a...)}
quickSortRec(a, 0, len(a)-1, &frames)
return frames
}quickSortRec function · go · L373-L390 (18 LOC)viz.go
func quickSortRec(a []int, lo, hi int, frames *[][]int) {
if lo >= hi {
return
}
pivot := a[hi]
i := lo
for j := lo; j < hi; j++ {
if a[j] < pivot {
a[i], a[j] = a[j], a[i]
*frames = append(*frames, append([]int(nil), a...))
i++
}
}
a[i], a[hi] = a[hi], a[i]
*frames = append(*frames, append([]int(nil), a...))
quickSortRec(a, lo, i-1, frames)
quickSortRec(a, i+1, hi, frames)
}page 1 / 2next ›