Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2011-03-09 04:04:04 +0300
committerisaacs <i@izs.me>2011-03-22 01:55:54 +0300
commit7fa48daf31bbf96a73a886b2d844e6eb04d569da (patch)
treee3613e205aaaa1daad4beb2a28c568f762a78aaa /lib/search.js
parentea43a3d6421a10056041c1c17f3d2aa17340a74c (diff)
Much nicer search implementation.
Diffstat (limited to 'lib/search.js')
-rw-r--r--lib/search.js260
1 files changed, 117 insertions, 143 deletions
diff --git a/lib/search.js b/lib/search.js
index 62d392770..9fea92025 100644
--- a/lib/search.js
+++ b/lib/search.js
@@ -47,8 +47,13 @@ function search (args, silent, staleness, cb_) {
if (typeof searchexclude === "string") {
searchexclude = searchexclude.split(/\s+/)
} else searchexclude = []
- getFilteredData( staleness, searchopts.concat(args), searchexclude
- , function (er, data) {
+ var opts = searchopts.concat(args).map(function (s) {
+ return s.toLowerCase()
+ }).filter(function (s) { return s })
+ searchexclude = searchexclude.map(function (s) {
+ return s.toLowerCase()
+ })
+ getFilteredData( staleness, opts, searchexclude, function (er, data) {
// now data is the list of data that we want to show.
// prettify and print it, and then provide the raw
// data to the cb.
@@ -60,117 +65,63 @@ function search (args, silent, staleness, cb_) {
}
function getFilteredData (staleness, args, notArgs, cb) {
- var processedData = {}
- getMergedData(staleness, function (er, data) {
+ registry.get("/", null, staleness, function (er, data) {
if (er) return cb(er)
- Object.keys(data).sort(strcmp).forEach(function (p) {
- var pkg = data[p]
- if (pkg.url && (!pkg.versions || !Object.keys(pkg.versions).length)) {
- processedData[pkg.name] = getWords(pkg)
- } else {
- Object.keys(pkg.versions).sort(semver.compare).forEach(function (v) {
- pkg.name = p
- processedData[pkg.name+"@"+v] = getWords(pkg, v)
- })
- }
- })
- var filtered = {}
- Object.keys(processedData).forEach(function (name) {
- var d = processedData[name]
- , pass = true
- , test = [name].concat(npm.config.get("description")
- ? d.description : [])
- .concat(d.keywords)
- .concat(d.words)
- for (var i = 0, l = args.length; i < l; i ++) {
- pass = false
- for (var ii = 0, ll = test.length; ii < ll; ii ++) {
- if (test[ii].indexOf(args[i]) !== -1) {
- pass = true
- break
- }
- }
- if (!pass) break
- }
- if (pass) for (var i = 0, l = notArgs.length; i < l; i ++) {
- for (var ii = 0, ll = test.length; ii < ll; ii ++) {
- if (test[ii].indexOf(notArgs[i]) !== -1) {
- pass = false
- break
- }
- }
- if (!pass) break
- }
- if (pass) filtered[name] = d
- })
- return cb(null, filtered)
+ return cb(null, filter(data, args, notArgs))
})
}
-function getWords (pkg, version) {
- var d = { data : pkg
- , words : []
- , name : pkg.name + (version ? "@" + version : "")
- }
- if (pkg.maintainers && pkg.maintainers.length) {
- d.words.push.apply(d.words, pkg.maintainers.map(function (m) {
- return "=" + m.name
- }))
- }
- var desc = pkg.description
- , kw = pkg.keywords
- if (pkg.url && !version) {
- d.words.push("<"+pkg.url+">")
- } else {
- var v = pkg.versions[version]
- if (v.description) desc = v.description
- if (v.keywords) kw = v.keywords
- if (v.tags.length) d.words.push.apply(d.words, v.tags)
- if (v.active) d.words.push("active")
- }
- if (!kw) kw = []
- if (!Array.isArray(kw)) kw = kw.split(/\s+/)
- d.keywords = kw
- d.description = npm.config.get("description") && desc || ""
- return d
+function filter (data, args, notArgs) {
+ // data={<name>:{package data}}
+ return Object.keys(data).map(function (d) {
+ return data[d]
+ }).map(stripData).map(getWords).filter(function (data) {
+ return filterWords(data, args, notArgs)
+ }).reduce(function (l, r) {
+ l[r.name] = r
+ return l
+ }, {})
}
-function getMergedData (staleness, cb) {
- registry.get("/", null, staleness, function (er, remote) {
- if (er) return cb(er)
- return cb(null, merge(remote))
- })
+function stripData (data) {
+ return { name:data.name
+ , description:npm.config.get("description") ? data.description : ""
+ , maintainers:data.maintainers.map(function (m) {
+ return "=" + m.name
+ })
+ , url:!Object.keys(data.versions).length ? data.url : null
+ , keywords:data.keywords || []
+ }
}
-function strcmp (a, b) {
- a = a.toLowerCase()
- b = b.toLowerCase()
- return a === b ? 0 : a > b ? 1 : -1
+function getWords (data) {
+ data.words = [ data.name ]
+ .concat(data.description)
+ .concat(data.maintainers)
+ .concat(data.url && ("<" + data.url + ">"))
+ .concat(data.keywords)
+ .map(function (f) { return f && f.trim && f.trim() })
+ .filter(function (f) { return f })
+ .join(" ")
+ .toLowerCase()
+ return data
}
-function prettify (data, args) {
- var pkgs = Object.keys(data)
- , attrs = []
- , names = []
- , pretty = []
- , beginAttrList = 28
- pkgs.forEach(function (name) {
- var pkg = data[name]
- pretty.push({name:name,attrs:data[name].words.sort(strcmp).join(" ")
- ,description:data[name].description
- ,keywords:data[name].keywords})
- })
- var colors = [36, 32, 33, 31, 35 ]
- , c = 0
- , l = colors.length
- var maxNameLen = 0
- var space = " "
- pretty.forEach(function (line) {
- maxNameLen = Math.min(Math.max(maxNameLen, line.name.length), space.length)
- })
- maxNameLen += 2
+function filterWords (data, args, notArgs) {
+ var words = data.words
+ for (var i = 0, l = args.length; i < l; i ++) {
+ if (words.indexOf(args[i]) === -1) {
+ //console.error("fail %j", [args[i], words])
+ return false
+ }
+ }
+ for (var i = 0, l = notArgs.length; i < l; i ++) {
+ if (words.indexOf(notArgs[i]) !== -1) return false
+ }
+ return true
+}
- // turn each line obj into a single line, only as much ws as necessary.
+function prettify (data, args) {
try {
var stdio = process.binding("stdio")
, cols = stdio.isatty(stdio.stdoutFD) ?
@@ -178,50 +129,73 @@ function prettify (data, args) {
: stdio.getWindowSize ? stdio.getWindowSize()[1]
: Infinity )
: Infinity
- }
- catch (ex) { cols = Infinity }
- pretty = pretty.map(function (line) {
- var addSpace = maxNameLen - line.name.length
- return (line.name + (space.substr(0, addSpace) || "") + " "
- + line.attrs + " "
- + (line.description ? line.description + " " : "")
- + (line.keywords.length ? " " + line.keywords.join(" ") : ""))
- .substr(0, cols)
- })
+ } catch (ex) { cols = Infinity }
- if (args && pretty.length) args.forEach(function (arg) {
- pretty = pretty.map(function (line) {
- return line.split(arg).join("\033["+colors[c]+"m" + arg + "\033[m")
+ // name, desc, author, keywords
+ var longest = []
+ , spaces
+ , maxLen = [20, 80, 25]
+ return Object.keys(data).map(function (d) {
+ return data[d]
+ }).map(function (data) {
+ // turn a pkg data into a string
+ // [name,who,desc,targets,keywords] tuple
+ // also set longest to the longest name
+ if (typeof data.keywords === "string") {
+ data.keywords = data.keywords.split(/[,\s]+/)
+ }
+ if (!Array.isArray(data.keywords)) data.keywords = []
+ var l = [ data.name
+ , data.description || ""
+ , data.maintainers.join(" ")
+ , (data.keywords || []).join(" ")
+ ]
+ l.forEach(function (s, i) {
+ longest[i] = Math.min(maxLen[i] || Infinity
+ ,Math.max(longest[i] || 0, s.length))
+ l[i] = l[i].replace(/\s+/g, " ")
})
- c = (c + 1) % l
- })
- if (!pretty.length) pretty = ["Nothing found"]
- pretty.push("")
- return pretty.join("\n")
+ return l
+ }).map(function (line) {
+ return line.map(function (s, i) {
+ spaces = spaces || longest.map(function (n) {
+ return new Array(n + 2).join(" ")
+ })
+ return (s + spaces[i].substr(s.length))
+ }).join(" ").substr(0, cols)
+ }).sort(function (a, b) {
+ return a === b ? 0 : a > b ? 1 : -1
+ }).map(function (line) {
+ // colorize!
+ args.forEach(function (arg, i) {
+ line = addColorMarker(line, arg, i)
+ })
+ return colorize(line)
+ }).join("\n")
}
-function merge (remote) {
- var merged = {}
- // now merge in the remote stuff.
- for (var p in remote) {
- merged[p] = merged[p] || {versions:{}}
- for (var d in remote[p]) if (!merged[p].hasOwnProperty(d)) {
- merged[p][d] = remote[p][d]
- }
- for (var v in remote[p].versions) {
- merged[p].versions[v] = merged[p].versions[v] || {}
- merged[p].versions[v].tags = []
- var descs = remote[p].descriptions
- if (descs && descs[v] && descs[v] !== remote[p].description) {
- merged[p].versions[v].description = descs[v]
- }
- Object.keys(remote[p]["dist-tags"]).forEach(function (tag) {
- if (remote[p]["dist-tags"][tag] === v) {
- merged[p].versions[v].tags.push(tag)
- }
- })
- }
+var colors = [36, 32, 33, 31, 35 ]
+ , cl = colors.length
+function addColorMarker (str, arg, i) {
+ var m = i % cl + 1
+ , markStart = String.fromCharCode(m)
+ , markEnd = String.fromCharCode(0)
+ , pieces = str.toLowerCase().split(arg)
+ , p = 0
+ return pieces.map(function (piece, i) {
+ piece = str.substr(p, piece.length)
+ var mark = markStart
+ + str.substr(p+piece.length, arg.length)
+ + markEnd
+ p += piece.length + arg.length
+ return piece + mark
+ }).join("")
+ return str.split(arg).join(mark)
+}
+function colorize (line) {
+ for (var i = 0; i < cl; i ++) {
+ var m = i + 1
+ line = line.split(String.fromCharCode(m)).join("\033["+colors[i]+"m")
}
- return merged
+ return line.split("\u0000").join("\033[0m")
}
-