]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/lib/search.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / lib / search.js
1
2 module.exports = exports = search
3
4 var npm = require("./npm.js")
5   , columnify = require("columnify")
6   , updateIndex = require("./cache/update-index.js")
7
8 search.usage = "npm search [some search terms ...]"
9
10 search.completion = function (opts, cb) {
11   var compl = {}
12     , partial = opts.partialWord
13     , ipartial = partial.toLowerCase()
14     , plen = partial.length
15
16   // get the batch of data that matches so far.
17   // this is an example of using npm.commands.search programmatically
18   // to fetch data that has been filtered by a set of arguments.
19   search(opts.conf.argv.remain.slice(2), true, function (er, data) {
20     if (er) return cb(er)
21     Object.keys(data).forEach(function (name) {
22       data[name].words.split(" ").forEach(function (w) {
23         if (w.toLowerCase().indexOf(ipartial) === 0) {
24           compl[partial + w.substr(plen)] = true
25         }
26       })
27     })
28     cb(null, Object.keys(compl))
29   })
30 }
31
32 function search (args, silent, staleness, cb) {
33   if (typeof cb !== "function") cb = staleness, staleness = 600
34   if (typeof cb !== "function") cb = silent, silent = false
35
36   var searchopts = npm.config.get("searchopts")
37   var searchexclude = npm.config.get("searchexclude")
38
39   if (typeof searchopts !== "string") searchopts = ""
40   searchopts = searchopts.split(/\s+/)
41   var opts = searchopts.concat(args).map(function (s) {
42     return s.toLowerCase()
43   }).filter(function (s) { return s })
44
45   if (typeof searchexclude === "string") {
46     searchexclude = searchexclude.split(/\s+/)
47   } else {
48     searchexclude = []
49   }
50   searchexclude = searchexclude.map(function (s) {
51     return s.toLowerCase()
52   })
53
54   getFilteredData(staleness, opts, searchexclude, function (er, data) {
55     // now data is the list of data that we want to show.
56     // prettify and print it, and then provide the raw
57     // data to the cb.
58     if (er || silent) return cb(er, data)
59     console.log(prettify(data, args))
60     cb(null, data)
61   })
62 }
63
64 function getFilteredData (staleness, args, notArgs, cb) {
65   updateIndex(staleness, function (er, data) {
66     if (er) return cb(er)
67     return cb(null, filter(data, args, notArgs))
68   })
69 }
70
71 function filter (data, args, notArgs) {
72   // data={<name>:{package data}}
73   return Object.keys(data).map(function (d) {
74     return data[d]
75   }).filter(function (d) {
76     return typeof d === "object"
77   }).map(stripData).map(getWords).filter(function (data) {
78     return filterWords(data, args, notArgs)
79   }).reduce(function (l, r) {
80     l[r.name] = r
81     return l
82   }, {})
83 }
84
85 function stripData (data) {
86   return { name: data.name
87          , description: npm.config.get("description") ? data.description : ""
88          , maintainers: (data.maintainers || []).map(function (m) {
89              return "=" + m.name
90            })
91          , url: !Object.keys(data.versions || {}).length ? data.url : null
92          , keywords: data.keywords || []
93          , version: Object.keys(data.versions || {})[0] || []
94          , time: data.time
95                  && data.time.modified
96                  && (new Date(data.time.modified).toISOString()
97                      .split("T").join(" ")
98                      .replace(/:[0-9]{2}\.[0-9]{3}Z$/, ""))
99                      .slice(0, -5) // remove time
100                  || "prehistoric"
101          }
102 }
103
104 function getWords (data) {
105   data.words = [ data.name ]
106                .concat(data.description)
107                .concat(data.maintainers)
108                .concat(data.url && ("<" + data.url + ">"))
109                .concat(data.keywords)
110                .map(function (f) { return f && f.trim && f.trim() })
111                .filter(function (f) { return f })
112                .join(" ")
113                .toLowerCase()
114   return data
115 }
116
117 function filterWords (data, args, notArgs) {
118   var words = data.words
119   for (var i = 0, l = args.length; i < l; i ++) {
120     if (!match(words, args[i])) return false
121   }
122   for (i = 0, l = notArgs.length; i < l; i ++) {
123     if (match(words, notArgs[i])) return false
124   }
125   return true
126 }
127
128 function match (words, arg) {
129   if (arg.charAt(0) === "/") {
130     arg = arg.replace(/\/$/, "")
131     arg = new RegExp(arg.substr(1, arg.length - 1))
132     return words.match(arg)
133   }
134   return words.indexOf(arg) !== -1
135 }
136
137 function prettify (data, args) {
138   var searchsort = (npm.config.get("searchsort") || "NAME").toLowerCase()
139     , sortField = searchsort.replace(/^\-+/, "")
140     , searchRev = searchsort.charAt(0) === "-"
141     , truncate = !npm.config.get("long")
142
143   if (Object.keys(data).length === 0) {
144     return "No match found for "+(args.map(JSON.stringify).join(" "))
145   }
146
147   var lines = Object.keys(data).map(function (d) {
148     // strip keyname
149     return data[d]
150   }).map(function(dat) {
151     dat.author = dat.maintainers
152     delete dat.maintainers
153     dat.date = dat.time
154     delete dat.time
155     return dat
156   }).map(function(dat) {
157     // split keywords on whitespace or ,
158     if (typeof dat.keywords === "string") {
159       dat.keywords = dat.keywords.split(/[,\s]+/)
160     }
161     if (Array.isArray(dat.keywords)) {
162       dat.keywords = dat.keywords.join(" ")
163     }
164
165     // split author on whitespace or ,
166     if (typeof dat.author === "string") {
167       dat.author = dat.author.split(/[,\s]+/)
168     }
169     if (Array.isArray(dat.author)) {
170       dat.author = dat.author.join(" ")
171     }
172     return dat
173   })
174
175   lines.sort(function(a, b) {
176     var aa = a[sortField].toLowerCase()
177       , bb = b[sortField].toLowerCase()
178     return aa === bb ? 0
179          : aa < bb ? -1 : 1
180   })
181
182   if (searchRev) lines.reverse()
183
184   var columns = npm.config.get("description")
185                ? ["name", "description", "author", "date", "version", "keywords"]
186                : ["name", "author", "date", "version", "keywords"]
187
188   var output = columnify(lines, {
189         include: columns
190       , truncate: truncate
191       , config: {
192           name: { maxWidth: 40, truncate: false, truncateMarker: "" }
193         , description: { maxWidth: 60 }
194         , author: { maxWidth: 20 }
195         , date: { maxWidth: 11 }
196         , version: { maxWidth: 11 }
197         , keywords: { maxWidth: Infinity }
198       }
199   })
200   output = trimToMaxWidth(output)
201   output = highlightSearchTerms(output, args)
202
203   return output
204 }
205
206 var colors = [31, 33, 32, 36, 34, 35 ]
207   , cl = colors.length
208
209 function addColorMarker (str, arg, i) {
210   var m = i % cl + 1
211     , markStart = String.fromCharCode(m)
212     , markEnd = String.fromCharCode(0)
213
214   if (arg.charAt(0) === "/") {
215     //arg = arg.replace(/\/$/, "")
216     return str.replace( new RegExp(arg.substr(1, arg.length - 2), "gi")
217                       , function (bit) { return markStart + bit + markEnd } )
218
219   }
220
221   // just a normal string, do the split/map thing
222   var pieces = str.toLowerCase().split(arg.toLowerCase())
223     , p = 0
224
225   return pieces.map(function (piece) {
226     piece = str.substr(p, piece.length)
227     var mark = markStart
228              + str.substr(p+piece.length, arg.length)
229              + markEnd
230     p += piece.length + arg.length
231     return piece + mark
232   }).join("")
233 }
234
235 function colorize (line) {
236   for (var i = 0; i < cl; i ++) {
237     var m = i + 1
238     var color = npm.color ? "\033["+colors[i]+"m" : ""
239     line = line.split(String.fromCharCode(m)).join(color)
240   }
241   var uncolor = npm.color ? "\033[0m" : ""
242   return line.split("\u0000").join(uncolor)
243 }
244
245 function getMaxWidth() {
246   var cols
247   try {
248     var tty = require("tty")
249       , stdout = process.stdout
250     cols = !tty.isatty(stdout.fd) ? Infinity : process.stdout.getWindowSize()[0]
251     cols = (cols === 0) ? Infinity : cols
252   } catch (ex) { cols = Infinity }
253   return cols
254 }
255
256 function trimToMaxWidth(str) {
257   var maxWidth = getMaxWidth()
258   return str.split("\n").map(function(line) {
259     return line.slice(0, maxWidth)
260   }).join("\n")
261 }
262
263 function highlightSearchTerms(str, terms) {
264   terms.forEach(function (arg, i) {
265     str = addColorMarker(str, arg, i)
266   })
267
268   return colorize(str).trim()
269 }