Skip to content
Snippets Groups Projects
abbrev.js 1.72 KiB
Newer Older
  • Learn to ignore specific revisions
  • Jay's avatar
    Jay committed
    module.exports = exports = abbrev.abbrev = abbrev
    
    abbrev.monkeyPatch = monkeyPatch
    
    function monkeyPatch () {
      Object.defineProperty(Array.prototype, 'abbrev', {
        value: function () { return abbrev(this) },
        enumerable: false, configurable: true, writable: true
      })
    
      Object.defineProperty(Object.prototype, 'abbrev', {
        value: function () { return abbrev(Object.keys(this)) },
        enumerable: false, configurable: true, writable: true
      })
    }
    
    function abbrev (list) {
      if (arguments.length !== 1 || !Array.isArray(list)) {
        list = Array.prototype.slice.call(arguments, 0)
      }
      for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
        args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
      }
    
      // sort them lexicographically, so that they're next to their nearest kin
      args = args.sort(lexSort)
    
      // walk through each, seeing how much it has in common with the next and previous
      var abbrevs = {}
        , prev = ""
      for (var i = 0, l = args.length ; i < l ; i ++) {
        var current = args[i]
          , next = args[i + 1] || ""
          , nextMatches = true
          , prevMatches = true
        if (current === next) continue
        for (var j = 0, cl = current.length ; j < cl ; j ++) {
          var curChar = current.charAt(j)
          nextMatches = nextMatches && curChar === next.charAt(j)
          prevMatches = prevMatches && curChar === prev.charAt(j)
          if (!nextMatches && !prevMatches) {
            j ++
            break
          }
        }
        prev = current
        if (j === cl) {
          abbrevs[current] = current
          continue
        }
        for (var a = current.substr(0, j) ; j <= cl ; j ++) {
          abbrevs[a] = current
          a += current.charAt(j)
        }
      }
      return abbrevs
    }
    
    function lexSort (a, b) {
      return a === b ? 0 : a > b ? 1 : -1
    }