Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add last publish date to search results, and search sorting

  • Loading branch information...
commit 9232cee94d55af159f02d53540ec74e8b1b0ef44 1 parent 4b25fe7
@isaacs isaacs authored
View
10 doc/cli/config.md
@@ -545,6 +545,16 @@ Space-separated options that are always passed to search.
Space-separated options that limit the results from search.
+### searchsort
+
+* Default: "name"
+* Type: String
+* Values: "name", "-name", "date", "-date", "description",
+ "-description", "keywords", "-keywords"
+
+Indication of which field to sort search results by. Prefix with a `-`
+character to indicate reverse sort.
+
### shell
* Default: SHELL environment variable, or "bash" on Posix, or "cmd" on
View
28 doc/cli/search.md
@@ -9,31 +9,9 @@ npm-search(1) -- Search for packages
Search the registry for packages matching the search terms.
-If a term starts with `/` and ends with `/`, then it's interpreted as a
-regular expression.
-
-## CONFIGURATION
-
-### description
-
-* Default: true
-* Type: Boolean
-
-Show the description in `npm search`
-
-### searchopts
-
-* Default: ""
-* Type: String
-
-Space-separated options that are always passed to search.
-
-### searchexclude
-
-* Default: ""
-* Type: String
-
-Space-separated options that limit the results from search.
+If a term starts with `/`, then it's interpreted as a regular expression.
+A trailing `/` will be ignored in this case. (Note that many regular
+expression characters must be escaped or quoted in most shells.)
## SEE ALSO
View
54 lib/search.js
@@ -82,13 +82,19 @@ function filter (data, args, notArgs) {
}
function stripData (data) {
- return { name:data.name
- , description:npm.config.get("description") ? data.description : ""
- , maintainers:(data.maintainers || []).map(function (m) {
+ 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 || []
+ , url: !Object.keys(data.versions || {}).length ? data.url : null
+ , keywords: data.keywords || []
+ , time: data.time
+ && data.time.modified
+ && (new Date(data.time.modified).toISOString()
+ .split("T").join(" ")
+ .replace(/:[0-9]{2}\.[0-9]{3}Z$/, ""))
+ || "(prehistoric)"
}
}
@@ -117,8 +123,9 @@ function filterWords (data, args, notArgs) {
}
function match (words, arg) {
- if (arg.charAt(0) === "/" && arg.slice(-1) === "/") {
- arg = new RegExp(arg.substr(1, arg.length - 2))
+ if (arg.charAt(0) === "/") {
+ arg = arg.replace(/\/$/, "")
+ arg = new RegExp(arg.substr(1, arg.length - 1))
return words.match(arg)
}
return words.indexOf(arg) !== -1
@@ -136,14 +143,24 @@ function prettify (data, args) {
// name, desc, author, keywords
var longest = []
, spaces
- , maxLen = [20, 60, 20, Infinity]
- , headings = ["NAME", "DESCRIPTION", "AUTHOR", "KEYWORDS"]
+ , maxLen = npm.config.get("description")
+ ? [20, 60, 20, 20, Infinity]
+ : [20, 20, 20, Infinity]
+ , headings = npm.config.get("description")
+ ? ["NAME", "DESCRIPTION", "AUTHOR", "DATE", "KEYWORDS"]
+ : ["NAME", "AUTHOR", "DATE", "KEYWORDS"]
, lines
+ , searchsort = (npm.config.get("searchsort") || "NAME").toLowerCase()
+ , sortFields = { name: 0
+ , description: 1
+ , author: 2
+ , date: 3
+ , keywords: 4 }
+ , searchRev = searchsort.charAt(0) === "-"
+ , sortField = sortFields[searchsort.replace(/^\-+/, "")]
lines = Object.keys(data).map(function (d) {
return data[d]
- }).filter(function (data) {
- return data.name
}).map(function (data) {
// turn a pkg data into a string
// [name,who,desc,targets,keywords] tuple
@@ -155,6 +172,7 @@ function prettify (data, args) {
var l = [ data.name
, data.description || ""
, data.maintainers.join(" ")
+ , data.time
, (data.keywords || []).join(" ")
]
l.forEach(function (s, i) {
@@ -168,6 +186,13 @@ function prettify (data, args) {
l[i] = l[i].replace(/\s+/g, " ")
})
return l
+ }).sort(function (a, b) {
+ // a and b are "line" objects of [name, desc, maint, time, kw]
+ var aa = a[sortField].toLowerCase()
+ , bb = b[sortField].toLowerCase()
+ return aa === bb ? 0
+ : aa < bb ? (searchRev ? 1 : -1)
+ : (searchRev ? -1 : 1)
}).map(function (line) {
return line.map(function (s, i) {
spaces = spaces || longest.map(function (n) {
@@ -179,8 +204,6 @@ function prettify (data, args) {
}
return s + spaces[i].substr(len)
}).join(" ").substr(0, cols).trim()
- }).sort(function (a, b) {
- return a === b ? 0 : a > b ? 1 : -1
}).map(function (line) {
// colorize!
args.forEach(function (arg, i) {
@@ -208,8 +231,9 @@ function addColorMarker (str, arg, i) {
, markStart = String.fromCharCode(m)
, markEnd = String.fromCharCode(0)
- if (arg.charAt(0) === "/" && arg.slice(-1) === "/") {
- return str.replace( new RegExp(arg.substr(1, arg.length - 2), "gi")
+ if (arg.charAt(0) === "/") {
+ //arg = arg.replace(/\/$/, "")
+ return str.replace( new RegExp(arg.substr(1, arg.length - 1), "gi")
, function (bit) { return markStart + bit + markEnd } )
}
View
6 lib/utils/config-defs.js
@@ -183,6 +183,7 @@ Object.defineProperty(exports, "defaults", {get: function () {
, save : false
, searchopts: ""
, searchexclude: null
+ , searchsort: "name"
, shell : process.platform === "win32"
? process.env.ComSpec || "cmd"
: process.env.SHELL || "bash"
@@ -256,6 +257,11 @@ exports.types =
, save : Boolean
, searchopts : String
, searchexclude: [null, String]
+ , searchsort: [ "name", "-name"
+ , "description", "-description"
+ , "author", "-author"
+ , "date", "-date"
+ , "keywords", "-keywords" ]
, shell : String
, "strict-ssl": Boolean
, tag : String
Please sign in to comment.
Something went wrong with that request. Please try again.