{"id":30623400,"url":"https://github.com/3rd/picoprint","last_synced_at":"2026-01-20T17:03:05.175Z","repository":{"id":311335190,"uuid":"1043502314","full_name":"3rd/picoprint","owner":"3rd","description":null,"archived":false,"fork":false,"pushed_at":"2025-08-24T02:33:08.000Z","size":97,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-24T08:12:24.596Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/3rd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-24T01:58:24.000Z","updated_at":"2025-08-24T02:33:11.000Z","dependencies_parsed_at":"2025-08-24T08:48:22.358Z","dependency_job_id":"a31ef803-8a6c-425d-8b04-89d69eb7dc01","html_url":"https://github.com/3rd/picoprint","commit_stats":null,"previous_names":["3rd/picoprint"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/3rd/picoprint","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3rd%2Fpicoprint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3rd%2Fpicoprint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3rd%2Fpicoprint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3rd%2Fpicoprint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/3rd","download_url":"https://codeload.github.com/3rd/picoprint/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3rd%2Fpicoprint/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28607624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T16:10:39.856Z","status":"ssl_error","status_checked_at":"2026-01-20T16:10:39.493Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-30T16:17:02.429Z","updated_at":"2026-01-20T17:03:05.168Z","avatar_url":"https://github.com/3rd.png","language":"TypeScript","readme":"# picoprint\n\nA tiny, fast, and feature-rich pretty printer for the terminal with zero dependencies.\n\n## Installation\n\n```bash\nbun add picoprint\n# or\npnpm add picoprint\n# or\nnpm install picoprint\n```\n\n## Quick Start\n\n```typescript\nimport p from 'picoprint';\n\n// Pretty print any value\np({ name: 'Alice', age: 30, hobbies: ['reading', 'coding'] });\n\n// Use colors\np.green.log('Success!');\np.bgRed.white.log('ERROR');\n\n// Quick logging (indent-aware)\np.log('server', 'listening on', 3000);\n\n// Control global indentation\np.indent();\np.log('within a block'); // printed with 2-space indent\np.indent(3);\np.log('deeper');         // printed with 5-space indent\np.dedent(); // pops one prior indent level\np.log('back to 2');\np.dedent();\np.log('back to 0');\n\n// Draw boxes\np.box('Hello World', {\n  style: 'rounded',\n  color: p.yellow,\n  padding: 1\n});\n```\n\n## Features\n\n- 🎨 **Rich formatting** - Colors, backgrounds, styles, gradients\n- 📦 **Box drawing** - Multiple border styles with padding and titles\n- 📊 **Tables** - Auto-formatted tables from arrays and objects\n- 🌳 **Trees** - Hierarchical tree structures with search\n- 🔍 **Diffs** - Visual object and text diffs\n- 💻 **Code highlighting** - Syntax highlighting with optional bat integration\n- 📅 **Calendars** - ASCII calendars with event markers\n- 🔄 **Streaming** - Streaming output for progressive rendering\n- 📝 **Logging** - `p.log` and chainable `.log` on colors (e.g., `p.yellow.log()`)\n\n### 🎨 Colors \u0026 Styling\n\n```typescript\n// Basic colors\np.red('Error'), p.green('Success'), p.yellow('Warning')\np.bgBlue.white('Highlighted')\n\n// Modifiers\np.bold('Bold'), p.dim('Dimmed'), p.italic('Italic')\np.underline('Underlined'), p.strikethrough('Strikethrough')\n\n// 256 colors\np.color256(196)('Red from 256 palette')\np.bgColor256(226)('Yellow background')\n\n// RGB \u0026 Hex\np.rgb(255, 128, 0)('Orange')\np.hex('#FF5733')('Coral')\np.bgRgb(0, 0, 255)('Blue background')\np.bgHex('#2E86AB')('Ocean background')\n\n// Gradients\np.gradient('Smooth gradient text', p.red, p.blue)\np.gradientRgb('RGB gradient', {r:255,g:0,b:0}, {r:0,g:0,b:255})\np.gradientHex('Hex gradient', '#FF0000', '#0000FF')\n\n// Rainbow \u0026 color palettes\np.rainbow('Rainbow text 🌈')\np.palette('#FF0000', 7) // Generate 7 shades\n\n// Logging with styles\np.yellow.log('warn:', 'disk', 95, '%')\np.bold.yellow.log('ready')\n// plain log\np.log('status', 200)\n```\n\n### 📦 Boxes\n\n```typescript\n// Basic box\np.box('Content here');\n\n// Styled boxes\np.box('Double border', { style: 'double', color: p.green });\np.box('Rounded box', { style: 'rounded', title: 'Info', color: p.cyan });\n\n// Box styles: single, double, rounded, thick, ascii\n\n// Box variants\np.box.frame('No padding frame', { color: p.red });\np.box.panel('Title', 'Panel content with rounded corners');\n\n// Capture console output\np.box(() =\u003e {\n  console.log('This output is captured');\n  console.log(p.green('With colors!'));\n}, { title: 'Captured', style: 'rounded' });\n\n// Box returns callback's return value\nconst result = p.box(() =\u003e {\n  console.log('Computing...');\n  return 42;\n}, { title: 'Process' });\n// result === 42\n\n// Background colors\np.box('Blue background', {\n  background: p.bgBlue,\n  padding: 1,\n  color: p.white\n});\n```\n\n### ➖ Lines\n\n```typescript\n// Simple line\np.line();\n\n// Line with label\np.line('Section Title');\n\n// Line styles\np.line({ style: 'double' });\np.line({ style: 'thick' });\np.line({ style: 'dashed' });\n\n// Shortcuts\np.line.double('Double Line');\np.line.thick('Thick Line');\np.line.dashed('Dashed');\np.line.section('Section');\n\n// Gradient line\np.line.gradient({ start: p.magenta, end: p.yellow });\n\n// Custom alignment\np.line({ label: 'Left', align: 'left' });\np.line({ label: 'Right', align: 'right' });\n```\n\n### 📊 Tables\n\n```typescript\n// Array of objects\np.table([\n  { name: 'Alice', age: 30, city: 'New York' },\n  { name: 'Bob', age: 25, city: 'London' }\n]);\n\n// Object as key-value pairs\np.table({ host: 'localhost', port: 3000, secure: true });\n\n// Map\np.table(new Map([['key1', 'value1'], ['key2', 'value2']]));\n\n// Table options\np.table(data, {\n  style: 'double',      // single, double, rounded, thick, ascii\n  showIndex: true,      // Show row numbers\n  columns: ['name', 'age'], // Select columns\n  align: { price: 'right', name: 'left' },\n  compact: true,\n  maxWidth: 20\n});\n\n// Compare two objects side-by-side\np.table.compare(\n  { port: 3000, host: 'localhost' },\n  { port: 8080, host: '0.0.0.0' }\n);\n```\n\n### 🌳 Trees\n\n```typescript\n// Basic tree\nconst tree = {\n  name: 'root',\n  children: [\n    { name: 'branch1' },\n    {\n      name: 'branch2',\n      children: [\n        { name: 'leaf1' },\n        { name: 'leaf2' }\n      ]\n    }\n  ]\n};\np.tree(tree);\n\n// Tree styles: unicode, ascii, rounded, double, bold\n\n// Tree with values \u0026 metadata\np.tree(tree, {\n  showValues: true,\n  showMetadata: true,\n  maxDepth: 3,\n  style: 'rounded'\n});\n\n// Convert object to tree\np.tree.fromObject({\n  user: { name: 'Alice', settings: { theme: 'dark' } }\n}, 'Config');\n\n// Search in tree\np.tree.search(tree, 'leaf');\n\n// Tree statistics\np.tree.stats(tree);\n\n// Multiple trees\np.tree.multi([tree1, tree2, tree3]);\n\n// Directory structure\nconst dir = {\n  name: 'src',\n  type: 'directory',\n  children: [\n    { name: 'index.ts', type: 'file', size: 2048 },\n    {\n      name: 'components',\n      type: 'directory',\n      children: [\n        { name: 'Button.tsx', type: 'file', size: 1024 }\n      ]\n    }\n  ]\n};\np.tree.directory(dir, {\n  fileIcons: true,\n  showSizes: true,\n  sortBy: 'type' // or 'name', 'size'\n});\n```\n\n### 💻 Code Highlighting\n\n```typescript\n// Basic syntax highlighting (uses bat if available)\np.code('const x = 42;', 'javascript');\n\n// Code with options\np.code(sourceCode, {\n  language: 'typescript',\n  lineNumbers: true,\n  window: 'rounded',      // Window border style\n  title: 'Example',\n  titleAlign: 'center',\n  padding: 1,\n  background: p.bgBlue,\n  borderColor: p.yellow,\n  titleColor: p.cyan\n});\n\n// Configure bat integration\np.configure({\n  code: {\n    useBat: true,\n    batTheme: 'TwoDark'\n  }\n});\n```\n\n### 🔍 Diffs\n\n```typescript\n// Object diff\np.diff(\n  { name: 'Alice', age: 30 },\n  { name: 'Alice', age: 31, city: 'NYC' }\n);\n\n// Options\np.diff(obj1, obj2, {\n  showUnchanged: true,\n  compact: false,\n  maxDepth: 3\n});\n\n// Word diff\np.diffWords('Hello world', 'Hello beautiful world');\np.diffWords(text1, text2, {\n  ignoreCase: true,\n  ignoreWhitespace: true\n});\n\n// Side-by-side comparison\np.compare(leftData, rightData);\np.compare(data1, data2, { labels: ['Dev', 'Prod'] });\n\n// Deep diff (returns diff nodes)\nconst changes = p.deepDiff(obj1, obj2);\n```\n\n### 📅 Calendar\n\n```typescript\n// Current month\np.calendar();\n\n// Specific date\np.calendar(new Date(2024, 2)); // March 2024\n\n// With options\np.calendar(date, {\n  showHeader: true,\n  showFooter: true,\n  showWeekNumbers: true,\n  firstDayOfWeek: 0 // 0=Sunday, 1=Monday\n});\n\n// Calendar with events\np.calendarWithEvents(new Date(), [\n  {\n    date: new Date(2024, 2, 15),\n    label: 'Meeting',\n    color: p.red,\n    priority: 'high'\n  }\n]);\n```\n\n### 🔄 Streaming\n\n```typescript\n// Stream table data\nconst stream = p.stream.table();\nstream.write({ id: 1, status: 'pending' });\nstream.write({ id: 2, status: 'complete' });\nstream.close();\n\n// Stream tree nodes\nconst treeStream = p.stream.tree();\ntreeStream.add({ name: 'node1', path: [] });\ntreeStream.add({ name: 'child', path: ['node1'] });\ntreeStream.close();\n\n// Stream boxes\nconst boxStream = p.stream.box({ title: 'Live Data' });\nboxStream.writeln('Line 1');\nboxStream.writeln('Line 2');\nboxStream.close();\n\n// Stream pretty printing\nconst ppStream = p.stream.pp();\nppStream.write({ data: 'value' });\nppStream.close();\n```\n\n### 🐛 Stack Traces\n\n```typescript\n// Enhanced error display\ntry {\n  someFunction();\n} catch (err) {\n  p.error(err);\n}\n\n// Current stack trace\np.trace();\n\n// Call stack\np.callStack();\n\n// Custom stack display\np.stack();\n```\n\n### ⚙️ Configuration\n\n```typescript\np.configure({\n  // Pretty print options\n  maxDepth: 5,\n  maxItems: 100,\n  compact: false,\n  sorted: true,\n  showHidden: false,\n  colors: true,\n\n  // Code highlighting\n  code: {\n    useBat: true,        // Use bat for syntax highlighting\n    batTheme: 'TwoDark', // Bat theme\n    batOptions: []       // Additional bat arguments\n  }\n});\n\n// Get current config\nconst config = p.getConfig();\n\n// Reset to defaults\np.resetConfig();\n```\n\n## API\n\nThe default export `p` is both a function and an object:\n\n- `p(value, options?)` - Pretty print any value\n- `p.{color}(text)` - All color functions\n- `p.log(...args)` - Print any args (indent-aware) and return string\n- `p.{color}.log(...args)` - Chain colors then print args\n- `p.box(content, options?)` - Draw boxes\n- `p.line(options?)` - Draw lines\n- `p.table(data, options?)` - Display tables\n- `p.tree(node, options?)` - Display trees\n- `p.code(code, options?)` - Syntax highlighting\n- `p.diff(a, b, options?)` - Show differences\n- `p.calendar(date?, options?)` - Display calendar\n- `p.stream.*` - Streaming variants\n- `p.indent(amount?)` - Increase global indent (default 2)\n- `p.dedent()` - Decrease by one prior `p.indent` level\n- And more...\n\nNote on indentation levels: each call to `p.indent(amount?)` pushes one level by the specified space amount (default 2). `p.dedent()` removes exactly one prior level per call; call it repeatedly to pop multiple levels.\n\n## Requirements\n\n- Node.js 22+\n- Optional: `bat` for enhanced syntax highlighting\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3rd%2Fpicoprint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F3rd%2Fpicoprint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3rd%2Fpicoprint/lists"}