Full Code of mafintosh/diffy for AI

master 82552aea61d6 cached
15 files
10.0 KB
3.2k tokens
10 symbols
1 requests
Download .txt
Repository: mafintosh/diffy
Branch: master
Commit: 82552aea61d6
Files: 15
Total size: 10.0 KB

Directory structure:
gitextract_fdxxyl45/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── examples/
│   ├── date.js
│   ├── enter-name.js
│   ├── exit.js
│   ├── fullscreen.js
│   ├── nested.js
│   └── slider.js
├── index.js
├── input.js
├── package.json
├── trim+newline.js
└── trim.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
node_modules


================================================
FILE: .travis.yml
================================================
sudo: false

language: node_js

node_js:
  - "9"
  - "8"
  - "6"

os:
  - linux


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2017 Mathias Buus

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# diffy

A tiny framework for building diff based interactive command line tools.

```
npm install diffy
```

[![Build Status](https://travis-ci.org/mafintosh/diffy.svg?branch=master)](https://travis-ci.org/mafintosh/diffy)

Basically React, but in the terminal powered by [ansi-diff](https://github.com/mafintosh/ansi-diff) and [neat-input](https://github.com/mafintosh/neat-input).

## Usage

``` js
var diffy = require('diffy')()
var trim = require('diffy/trim')

diffy.render(function () {
  return trim(`
    Hello user. The time is:
      ${new Date()}
    That is all for now
  `)
})

// re-render every 1s
setInterval(() => diffy.render(), 1000)
```

You can also use `diffy` to query input from a user

``` js
var diffy = require('diffy')()
var trim = require('diffy/trim')
var input = require('diffy/input')({style: style})
var names = []

input.on('update', () => diffy.render())
input.on('enter', (line) => names.push(line))

diffy.render(function () {
  return trim(`
    Enter your name: ${input.line()}
    List of names: ${names.join(', ')}
  `)
})

function style (start, cursor, end) {
  return start + '[' + (cursor || ' ') + ']' + end
}
```

See the examples folder for more.

## API

#### `var diffy = require('diffy')([options])`

Make a new diffy instance. Writes to stdout.

Options include:

``` js
{
  fullscreen: true // overtake the terminal like vim/less does
}
```

Note that if you use `fullscreen: true`, the terminal will be restored
on exit, even if your program crashes.

#### `diffy.render([function])`

Trigger a render and/or update the default render
function. A render function should simply return a string
containing the output you wish to display and then `diffy` will make sure to only print the diff.

#### `diffy.width`

Property containing the width of the terminal.

#### `diffy.height`

Property containing the height of the terminal.

#### `diffy.on('resize')`

Emitted when the terminal is resized. Triggers a render as well.

#### `diffy.on('render')`

Emitted just before a render happens.

#### `var input = require('diffy/input')()`

Get a [neat-input](https://github.com/mafintosh/neat-input) instance. Use this if you want to accept interactive input.

#### `var trim = require('diffy/trim')`

Helper function that trims and removes the indentation of a multiline string. Useful if you have a render function that returns an indented string like in the above example.

#### `var trim = require('diffy/trim+newline')`

Helper function that trims but adds a newline at the end

## Components

With diffy, components are just strings you compose together to form your application.
A bunch of modules already exists for this pattern, providing useful features.

* [watson/menu-string](https://github.com/watson/menu-string) - Generate a menu with selectable menu items as a string.
* [watson/progress-string](https://github.com/watson/progress-string) - Generate a CLI progress bar as a string that you can then output in any way you like.
* [mafintosh/scrollable-string](https://github.com/mafintosh/scrollable-string) - Generate a diff friendly string that is bounded by a configurable scroll box.

## Credits

Thank you to [@Fouad](https://github.com/Fouad) for donating the module name.

## License

MIT


================================================
FILE: examples/date.js
================================================
var diffy = require('../')()
var trim = require('../trim')

diffy.render(function () {
  return trim(`
    Hello user. The time is:
      ${new Date()}
    That is all for now
  `)
})

// re-render every 1s
setInterval(() => diffy.render(), 1000)


================================================
FILE: examples/enter-name.js
================================================
var diffy = require('../')()
var input = require('../input')({style: style})
var trim = require('../trim')

var names = []

input.on('update', () => diffy.render())
input.on('enter', (line) => names.push(line))

diffy.render(function () {
  return trim(`
    Enter your name: ${input.line()}
    List of names: ${names.join(', ')}
  `)
})

function style (start, cursor, end) {
  return start + '[' + (cursor || ' ') + ']' + end
}


================================================
FILE: examples/exit.js
================================================
var diffy = require('../')()
var trim = require('../trim')

var text = 'lowercase'

process.once('SIGINT', function () {
  text = 'UPPERCASE'
  diffy.render(render)
  process.nextTick(process.exit)
})

diffy.render(render)

// re-render every 1s
setInterval(() => diffy.render(), 1000)

function render () {
  return trim(`
    Hello world.
    Error should happen on last line:
    ${text}
  `)
}


================================================
FILE: examples/fullscreen.js
================================================
var diffy = require('../')({fullscreen: true})
var input = require('../input')()
var fs = require('fs')

var src = fs.readFileSync(__filename, 'utf-8')
var tmp = src
var upper = false

diffy.render(function () {
  return tmp
})

input.on('enter', function () {
  upper = !upper
  tmp = upper ? src.toUpperCase() : src
  diffy.render()
})


================================================
FILE: examples/nested.js
================================================
var diffy = require('../')()
var trim = require('../trim')

diffy.render(function () {
  return trim(`
    Hello user. The time is:
      ${nestedDate()}
    THERE SHOULD BE NO SPACE ABOVE THIS LINE
    That is all for now
  `)
})

// re-render every 1s
setInterval(() => diffy.render(), 1000)

function nestedDate () {
  return trim(`
    ${new Date()}
  `)
}


================================================
FILE: examples/slider.js
================================================
var diffy = require('../')()
var input = require('../input')()

var pos = 0
var ch = '>'

input.on('left', function () {
  pos--
  ch = '<'
  diffy.render()
})

input.on('right', function () {
  pos++
  ch = '>'
  diffy.render()
})

diffy.render(render)

function render () {
  if (pos < 1) pos = 1
  var widLen = diffy.width.toString().length
  var wid = Math.max(diffy.width - 2 * widLen - 1 - 6, 10)
  if (pos >= wid - 1) pos = wid - 2
  var i = 1
  var s = 'Move the cursor <left> or <right>\n['
  for (; i < pos; i++) s += ' '
  s += ch
  i++
  for (; i < wid - 1; i++) s += ' '
  s += '] ' + (pos - 1) + '/' + (wid - 3) + '\n'
  if (ch === '>') s += 'You are moving <right>'
  else s += 'You are moving <left>'
  return s
}


================================================
FILE: index.js
================================================
var differ = require('ansi-diff')
var events = require('events')
var util = require('util')

var SMCUP = Buffer.from([0x1b, 0x5b, 0x3f, 0x31, 0x30, 0x34, 0x39, 0x68])
var RMCUP = Buffer.from([0x1b, 0x5b, 0x3f, 0x31, 0x30, 0x34, 0x39, 0x6c])
var CLEAR = Buffer.from([0x1b, 0x5b, 0x33, 0x4a, 0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a])

module.exports = Diffy

function Diffy (opts) {
  if (!(this instanceof Diffy)) return new Diffy(opts)
  if (!opts) opts = {}
  if (typeof opts === 'function') opts = {render: opts}

  events.EventEmitter.call(this)

  this.destroyed = false
  this.fullscreen = !!opts.fullscreen
  this.out = process.stdout
  this.out.on('resize', this._onresize.bind(this))
  this.differ = differ(this._dimension())

  this._destroy = this.destroy.bind(this)
  this._isFullscreen = false

  process.on('SIGWINCH', noop)
  process.on('exit', this._destroy)

  if (opts.render) this.render(opts.render)
}

util.inherits(Diffy, events.EventEmitter)

Object.defineProperty(Diffy.prototype, 'height', {
  enumerable: true,
  get: function () {
    return this.differ.height
  }
})

Object.defineProperty(Diffy.prototype, 'width', {
  enumerable: true,
  get: function () {
    return this.differ.width
  }
})

Diffy.prototype.render = function (fn) {
  if (this.fullscreen && !this._isFullscreen) {
    this._isFullscreen = true
    this.out.write(SMCUP)
    this.out.write(CLEAR)
  }
  if (fn) this._render = fn
  this.emit('render')
  this.out.write(this.differ.update(this._render()))
}

Diffy.prototype.destroy = function () {
  if (this.destroyed) return
  this.destroyed = true
  process.removeListener('SIGWINCH', noop)
  process.removeListener('exit', this._destroy)
  if (this._isFullscreen) this.out.write(RMCUP)
  this.emit('destroy')
}

Diffy.prototype._onresize = function () {
  this.differ.resize(this._dimension())
  this.emit('resize')
  this.render()
}

Diffy.prototype._dimension = function () {
  return {
    width: this.out.columns,
    height: this.out.rows
  }
}

function noop () {
  return ''
}


================================================
FILE: input.js
================================================
module.exports = require('neat-input')


================================================
FILE: package.json
================================================
{
  "name": "diffy",
  "version": "2.1.0",
  "description": "A tiny framework for building diff based interactive command line tools.",
  "main": "index.js",
  "dependencies": {
    "ansi-diff": "^1.0.10",
    "neat-input": "^1.9.0"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/mafintosh/diffy.git"
  },
  "scripts": {
    "test": "standard"
  },
  "author": "Mathias Buus (@mafintosh)",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/mafintosh/diffy/issues"
  },
  "homepage": "https://github.com/mafintosh/diffy",
  "devDependencies": {
    "standard": "^10.0.3"
  }
}


================================================
FILE: trim+newline.js
================================================
var trim = require('./trim')
var os = require('os')

module.exports = trimAndNewline

function trimAndNewline (s) {
  return trim(s) + os.EOL
}


================================================
FILE: trim.js
================================================

module.exports = trim

function trim (s) {
  if (!/^\r?\n/.test(s)) return s
  return deindent(s).trim()
}

function deindent (s) {
  if (!/^\r?\n/.test(s)) return s
  var indent = (s.match(/\n([ ]+)/m) || [])[1] || ''
  s = indent + s
  return s.split('\n')
    .map(l => replace(indent, l))
    .join('\n')
}

function replace (prefix, line) {
  return line.slice(0, prefix.length) === prefix ? line.slice(prefix.length) : line
}
Download .txt
gitextract_fdxxyl45/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── examples/
│   ├── date.js
│   ├── enter-name.js
│   ├── exit.js
│   ├── fullscreen.js
│   ├── nested.js
│   └── slider.js
├── index.js
├── input.js
├── package.json
├── trim+newline.js
└── trim.js
Download .txt
SYMBOL INDEX (10 symbols across 7 files)

FILE: examples/enter-name.js
  function style (line 17) | function style (start, cursor, end) {

FILE: examples/exit.js
  function render (line 17) | function render () {

FILE: examples/nested.js
  function nestedDate (line 16) | function nestedDate () {

FILE: examples/slider.js
  function render (line 21) | function render () {

FILE: index.js
  function Diffy (line 11) | function Diffy (opts) {
  function noop (line 82) | function noop () {

FILE: trim+newline.js
  function trimAndNewline (line 6) | function trimAndNewline (s) {

FILE: trim.js
  function trim (line 4) | function trim (s) {
  function deindent (line 9) | function deindent (s) {
  function replace (line 18) | function replace (prefix, line) {
Condensed preview — 15 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (11K chars).
[
  {
    "path": ".gitignore",
    "chars": 13,
    "preview": "node_modules\n"
  },
  {
    "path": ".travis.yml",
    "chars": 80,
    "preview": "sudo: false\n\nlanguage: node_js\n\nnode_js:\n  - \"9\"\n  - \"8\"\n  - \"6\"\n\nos:\n  - linux\n"
  },
  {
    "path": "LICENSE",
    "chars": 1079,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2017 Mathias Buus\n\nPermission is hereby granted, free of charge, to any person obta"
  },
  {
    "path": "README.md",
    "chars": 3261,
    "preview": "# diffy\n\nA tiny framework for building diff based interactive command line tools.\n\n```\nnpm install diffy\n```\n\n[![Build S"
  },
  {
    "path": "examples/date.js",
    "chars": 247,
    "preview": "var diffy = require('../')()\nvar trim = require('../trim')\n\ndiffy.render(function () {\n  return trim(`\n    Hello user. T"
  },
  {
    "path": "examples/enter-name.js",
    "chars": 431,
    "preview": "var diffy = require('../')()\nvar input = require('../input')({style: style})\nvar trim = require('../trim')\n\nvar names = "
  },
  {
    "path": "examples/exit.js",
    "chars": 398,
    "preview": "var diffy = require('../')()\nvar trim = require('../trim')\n\nvar text = 'lowercase'\n\nprocess.once('SIGINT', function () {"
  },
  {
    "path": "examples/fullscreen.js",
    "chars": 338,
    "preview": "var diffy = require('../')({fullscreen: true})\nvar input = require('../input')()\nvar fs = require('fs')\n\nvar src = fs.re"
  },
  {
    "path": "examples/nested.js",
    "chars": 361,
    "preview": "var diffy = require('../')()\nvar trim = require('../trim')\n\ndiffy.render(function () {\n  return trim(`\n    Hello user. T"
  },
  {
    "path": "examples/slider.js",
    "chars": 730,
    "preview": "var diffy = require('../')()\nvar input = require('../input')()\n\nvar pos = 0\nvar ch = '>'\n\ninput.on('left', function () {"
  },
  {
    "path": "index.js",
    "chars": 2035,
    "preview": "var differ = require('ansi-diff')\nvar events = require('events')\nvar util = require('util')\n\nvar SMCUP = Buffer.from([0x"
  },
  {
    "path": "input.js",
    "chars": 39,
    "preview": "module.exports = require('neat-input')\n"
  },
  {
    "path": "package.json",
    "chars": 615,
    "preview": "{\n  \"name\": \"diffy\",\n  \"version\": \"2.1.0\",\n  \"description\": \"A tiny framework for building diff based interactive comman"
  },
  {
    "path": "trim+newline.js",
    "chars": 144,
    "preview": "var trim = require('./trim')\nvar os = require('os')\n\nmodule.exports = trimAndNewline\n\nfunction trimAndNewline (s) {\n  re"
  },
  {
    "path": "trim.js",
    "chars": 433,
    "preview": "\nmodule.exports = trim\n\nfunction trim (s) {\n  if (!/^\\r?\\n/.test(s)) return s\n  return deindent(s).trim()\n}\n\nfunction de"
  }
]

About this extraction

This page contains the full source code of the mafintosh/diffy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 15 files (10.0 KB), approximately 3.2k tokens, and a symbol index with 10 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!