Skip to content

Commit ede88e4

Browse files
authored
Merge pull request #14 from bobadilla-tech/generate
Generate
2 parents d756c8b + 97a7860 commit ede88e4

File tree

8 files changed

+688
-36
lines changed

8 files changed

+688
-36
lines changed

claude.md

Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
# Lorelai Project Overview
2+
3+
## What is Lorelai?
4+
5+
Lorelai is a Go package and CLI tool for generating Lorem Ipsum placeholder text. It provides both random word generation and classic Lorem Ipsum text generation with a clean, simple API.
6+
7+
## Project Structure
8+
9+
```
10+
lorelai/
11+
├── cmd/ # CLI application
12+
│ └── root.go # Command-line interface implementation
13+
├── pkg/ # Core library package
14+
│ ├── root.go # Random Lorem generation functions
15+
│ ├── classic.go # Classic Lorem Ipsum functions
16+
│ ├── convenience.go # Utility functions (URL, Email, Domain)
17+
│ ├── data.go # Word corpus
18+
│ ├── tlds.go # Top-level domain data
19+
│ ├── utils.go # Internal helper functions
20+
│ └── *_test.go # Test files
21+
├── example/ # Example usage code
22+
└── readme.md # Documentation
23+
```
24+
25+
## Core Architecture
26+
27+
### Two Modes of Operation
28+
29+
**1. Random Mode** - Generates random Lorem Ipsum-like text:
30+
31+
- Uses a corpus of Latin words (`DATA` in `data.go`)
32+
- Randomly selects words for generation
33+
- Functions: `Word()`, `Sentence()`, `Paragraph()`, `Generate()`
34+
35+
**2. Classic Mode** - Uses traditional Lorem Ipsum text:
36+
37+
- Based on Cicero's "De finibus bonorum et malorum"
38+
- Always starts with "Lorem ipsum dolor sit amet..."
39+
- Functions: `ClassicWords()`, `ClassicSentence()`, `ClassicParagraph()`, `ClassicGenerate()`
40+
41+
### Key Design Patterns
42+
43+
#### 1. Consistent Naming Convention
44+
45+
All functions follow a clear pattern:
46+
47+
- Base functions for random mode: `Word()`, `Sentence()`, `Paragraph()`
48+
- Classic variants prefixed: `ClassicWord()`, `ClassicSentence()`, `ClassicParagraph()`
49+
50+
#### 2. Composition Over Complexity
51+
52+
- Simple, focused functions that do one thing well
53+
- No stateful services or complex object hierarchies
54+
- Functions compose easily: `Sentence()` uses `LoremWords(8)`
55+
56+
#### 3. Performance Optimizations
57+
58+
- Uses `strings.Builder` with capacity hints (`b.Grow()`)
59+
- Avoids unnecessary string concatenations
60+
- Thread-safe random generation with `math/rand/v2`
61+
62+
## API Design Philosophy
63+
64+
### Simplicity First
65+
66+
```go
67+
// Simple, direct API
68+
text := lorelai.Paragraph()
69+
70+
// Structured generation with metadata
71+
result := lorelai.Generate(3, 5)
72+
fmt.Printf("Generated %d words\n", result.WordCount)
73+
```
74+
75+
### Sensible Defaults
76+
77+
- Sentences are always 8 words
78+
- Paragraphs are always 45 words
79+
- All text is properly capitalized and punctuated
80+
81+
### No Configuration Required
82+
83+
- Zero-dependency operation (except stdlib)
84+
- No initialization or setup needed
85+
- Import and use immediately
86+
87+
## How Text Generation Works
88+
89+
### Random Mode Process
90+
91+
1. Select random words from `DATA` corpus
92+
2. Join words with spaces
93+
3. Capitalize first word
94+
4. Add period at end
95+
5. Return formatted string
96+
97+
### Classic Mode Process
98+
99+
1. Use sequential words from `classicText` array
100+
2. Start from beginning: "lorem", "ipsum", "dolor"...
101+
3. Wrap around if more words needed than available
102+
4. Format with capitalization and punctuation
103+
104+
### Structured Generation
105+
106+
Both `Generate()` and `ClassicGenerate()`:
107+
108+
1. Calculate total capacity needed
109+
2. Pre-allocate `strings.Builder` buffer
110+
3. Loop through paragraphs and sentences
111+
4. Insert separators (`\n\n` for paragraphs, space for sentences)
112+
5. Return `Lorem` struct with text and metadata
113+
114+
## Testing Strategy
115+
116+
### Test Coverage: 97.1%
117+
118+
**Unit Tests** cover:
119+
120+
- Individual function outputs (word counts, formatting)
121+
- Edge cases (0, negative numbers)
122+
- Formatting correctness (capitalization, punctuation)
123+
- Metadata accuracy
124+
125+
**Concurrent Tests** verify:
126+
127+
- Thread-safe random generation
128+
- No race conditions in word selection
129+
130+
**Integration Tests** ensure:
131+
132+
- CLI flags work correctly
133+
- File output functions properly
134+
- Colors render as expected
135+
136+
## CLI vs Package Semantics
137+
138+
### Important Distinction
139+
140+
**CLI** (additive behavior):
141+
142+
```bash
143+
lorelai -p 3 -s 5 # Generates 3 paragraphs + 5 sentences
144+
```
145+
146+
**Package** (multiplicative behavior):
147+
148+
```go
149+
lorelai.Generate(3, 5) // Generates 3 paragraphs OF 5 sentences each
150+
```
151+
152+
This difference is intentional:
153+
154+
- CLI optimized for quick, ad-hoc text generation
155+
- Package optimized for structured, programmatic use
156+
157+
## Convenience Features
158+
159+
Beyond Lorem Ipsum text, lorelai provides:
160+
161+
### Domain Names
162+
163+
```go
164+
lorelai.Domain() // "neque.net"
165+
```
166+
167+
### URLs
168+
169+
```go
170+
lorelai.URL() // "https://pellentesque.org"
171+
```
172+
173+
### Email Addresses
174+
175+
```go
176+
lorelai.Email() // "bibendum@id.pe"
177+
```
178+
179+
These use the same word corpus plus TLD (Top-Level Domain) data.
180+
181+
## Code Quality Practices
182+
183+
### 1. Clear Function Documentation
184+
185+
Every exported function has:
186+
187+
- Clear description of what it does
188+
- Input/output specifications
189+
- Usage examples where helpful
190+
191+
### 2. Efficient String Building
192+
193+
Always use `strings.Builder` with capacity hints:
194+
195+
```go
196+
var b strings.Builder
197+
b.Grow(expectedSize) // Pre-allocate
198+
```
199+
200+
### 3. DRY Principle
201+
202+
Common operations extracted to helpers:
203+
204+
- `formatWords()` - Capitalize and add punctuation
205+
- `capitalizeFirstWord()` - Title case first character
206+
- `trimSpaceAddDot()` - Clean up and punctuate
207+
208+
### 4. Defensive Programming
209+
210+
- Handle zero/negative inputs gracefully
211+
- Validate array bounds before access
212+
- Return empty strings for invalid input (not errors)
213+
214+
## Performance Characteristics
215+
216+
### Memory Efficiency
217+
218+
- Pre-allocated buffers reduce reallocations
219+
- `strings.Builder` avoids intermediate string copies
220+
- Fixed-size word corpus (`DATA` array)
221+
222+
### Time Complexity
223+
224+
- Random word selection: O(1)
225+
- Text generation: O(n) where n is output length
226+
- No complex algorithms or data structures
227+
228+
### Concurrency
229+
230+
- Thread-safe due to Go 1.22+ `math/rand/v2`
231+
- No shared mutable state
232+
- Functions are pure (aside from randomness)
233+
234+
## Common Use Cases
235+
236+
### 1. Web Development
237+
238+
Generate placeholder text for UI mockups:
239+
240+
```go
241+
description := lorelai.Paragraph()
242+
title := lorelai.Sentence()
243+
```
244+
245+
### 2. Testing
246+
247+
Create realistic test data:
248+
249+
```go
250+
for i := 0; i < 100; i++ {
251+
users[i].Bio = lorelai.Generate(2, 3).Text
252+
}
253+
```
254+
255+
### 3. Documentation
256+
257+
Fill example content in docs:
258+
259+
```go
260+
example := lorelai.ClassicGenerate(1, 2)
261+
```
262+
263+
### 4. CLI Quick Tasks
264+
265+
```bash
266+
lorelai -p 5 | pbcopy # Copy to clipboard
267+
lorelai -w 100 > file.txt # Save to file
268+
```
269+
270+
## Extending Lorelai
271+
272+
### Adding New Functions
273+
274+
Follow the established patterns:
275+
276+
1. **Name consistently**: `Thing()` for random, `ClassicThing()` for classic
277+
2. **Use helpers**: Reuse `formatWords()`, `capitalizeFirstWord()`
278+
3. **Add tests**: Include edge cases and format verification
279+
4. **Document**: Clear godoc comments with examples
280+
281+
### Adding New Features
282+
283+
Consider:
284+
285+
- Is it stateless? (Should be)
286+
- Does it fit the "simple text generation" domain?
287+
- Is the API obvious without reading docs?
288+
- Does it maintain backward compatibility?
289+
290+
## Dependencies
291+
292+
### Production
293+
294+
- **Zero external dependencies**
295+
- Uses only Go standard library
296+
- Minimum Go version: 1.22 (for `math/rand/v2`)
297+
298+
### Development/CLI
299+
300+
- `github.com/spf13/cobra` - CLI framework
301+
- `github.com/UltiRequiem/chigo/pkg` - Color output
302+
303+
## Project Philosophy
304+
305+
### Simplicity
306+
307+
> "Do one thing well" - Generate placeholder text, nothing more
308+
309+
### Pragmatism
310+
311+
> Sensible defaults over configuration. 8 words? Perfect. No need to change it.
312+
313+
### Accessibility
314+
315+
> Zero learning curve. Import, call a function, get text. Done.
316+
317+
### Performance
318+
319+
> Fast enough to not think about it. Pre-allocate, avoid copies, use `strings.Builder`.
320+
321+
## Maintenance Guidelines
322+
323+
### When Adding Code
324+
325+
- ✅ Maintain 95%+ test coverage
326+
- ✅ Keep functions small and focused
327+
- ✅ Follow existing naming patterns
328+
- ✅ Update documentation and examples
329+
330+
### When Reviewing PRs
331+
332+
- ❓ Does it add real value?
333+
- ❓ Is the API intuitive?
334+
- ❓ Are there tests?
335+
- ❓ Is it backward compatible?
336+
337+
### When Fixing Bugs
338+
339+
- 🐛 Add a test that reproduces the bug
340+
- 🐛 Fix the issue
341+
- 🐛 Verify the test passes
342+
- 🐛 Consider similar issues elsewhere
343+
344+
## Historical Context
345+
346+
Lorelai was created to provide a simple, dependency-free Lorem Ipsum generator for Go projects. Unlike other libraries that require configuration or complex APIs, Lorelai focuses on:
347+
348+
1. **Immediate usability** - No setup, just import and use
349+
2. **Predictable output** - Consistent word counts and formatting
350+
3. **Both modes** - Random for variety, classic for tradition
351+
4. **CLI included** - Quick shell usage without writing code
352+
353+
The project has grown to include convenience utilities (domains, URLs, emails) while maintaining its core simplicity.
354+
355+
---
356+
357+
_For implementation details and changes, see the Git history and PR discussions._

example/main.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ func printTonsOfText() {
2828
}
2929
}
3030

31+
func generateStructuredContent() {
32+
fmt.Println("\n=== Structured Random Lorem ===")
33+
// Generate 3 paragraphs with 5 sentences each
34+
result := lorelai.Generate(3, 5)
35+
fmt.Println(result.Text)
36+
fmt.Printf("\nGenerated %d words across %d paragraphs (%d sentences per paragraph)\n",
37+
result.WordCount, result.Paragraphs, result.Sentences)
38+
}
39+
40+
func generateClassicContent() {
41+
fmt.Println("\n=== Classic Lorem Ipsum ===")
42+
// Generate classic Lorem Ipsum text: 2 paragraphs with 4 sentences each
43+
result := lorelai.ClassicGenerate(2, 4)
44+
fmt.Println(result.Text)
45+
fmt.Printf("\nGenerated %d words of classic Lorem Ipsum\n", result.WordCount)
46+
}
47+
3148
func main() {
32-
printTonsOfText()
49+
generateStructuredContent()
50+
generateClassicContent()
3351
}

0 commit comments

Comments
 (0)