Skip to content

Commit d2eaca3

Browse files
authored
Search API backend (#28)
* Regenerate documentation * Snapshot of rework. - Moved names inside of the child list. - Set site_short_name to default to site_long_name if not declared * Revise approach to storing search portals Construct a single matrix storing both the long and short names of the site. From there, locate the site by index position and access it. * Not really "r" anymore... * Switch searcher() to use the new access system. The period after rlang came about due to a recursive warning: promise already under evaluation: recursive default argument reference or earlier problems? It would be nice to reference the rlang component. Not sure exactly why this variant is erroring vs. the prior * Generate documentation * Add default keyword option * Simplify code file... * Rename file... * On second thought, we're going to retain the function signatures. We'll lose the ability to specify though if rlang is on/off by default. * Prevent github folder from being picked up in package check build. * Protect if we do not supply a suffix. e.g. rscom no suffix is used. * Rewrite unit test for search handler as `rlang` is dropped. * Add a few notes * Avoid bitrot of unused code (still saved in version history...) * Rename file * Add two new test cases for keyword generation and site retrieval
1 parent f9fd980 commit d2eaca3

15 files changed

+194
-180
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
^cran-comments\.md$
77
^codecov\.yml$
88
^CRAN-RELEASE$
9+
^\.github$

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ Depends: R (>= 3.3.0)
1818
License: GPL (>= 2)
1919
Encoding: UTF-8
2020
LazyData: true
21-
RoxygenNote: 6.1.1
21+
RoxygenNote: 7.0.2
2222
Roxygen: list(markdown = TRUE)
2323
Suggests:
24-
testthat,
24+
testthat (>= 2.1.0),
2525
covr,
2626
knitr,
2727
rmarkdown

NEWS.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Features
44

55
- Allow RStudio's Viewer pane to display search results.
6-
- Note: This feature requires a patch per [issue 2252](https://github.com/rstudio/rstudio/issues/2252).
6+
- Note: This feature requires a patch per [rstudio/rstudio#2252](https://github.com/rstudio/rstudio/issues/2252).
77
([#21](https://github.com/r-assist/searcher/issues/21),
88
[#22](https://github.com/r-assist/searcher/pull/22))
99
- Added ability to set default package actions.
@@ -14,10 +14,20 @@
1414
- `searcher.use_rstudio_viewer` specifies whether RStudio's viewer pane should
1515
open the link instead of a web browser. Default is `FALSE` until RStudio's
1616
[sandbox issue](https://github.com/rstudio/rstudio/issues/2252) is resolved.
17+
- `searcher.default_keyword`: Suffix keyword to focus search results
18+
between either `"base"` or `"tidyverse"`. Default is `"base"`.
1719

20+
## Changes
21+
22+
- Function factory or a closure approach is now used to create
23+
search portal functions through `searcher()`.
24+
- `searcher()` function has lost the ability to specify `rlang` to address
25+
an unevaluated promise issue.
26+
1827
## Fixes
1928

20-
- Fixed vignette index name.
29+
- Addressed internal vignette index name being used as the title.
30+
- Block new CI/CD routines from being included with the package.
2131

2232
## Deployment
2333

R/index-sites.R

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
keyword_entry = function(base, tidyverse = base) {
2+
list(base = base, tidyverse = tidyverse)
3+
}
4+
5+
keyword_default = function() {
6+
keyword_entry("r programming", "tidyverse")
7+
}
8+
9+
#' Construct a Site Entry
10+
#'
11+
#' Encodes search portal information into a searchable list.
12+
#'
13+
#' @param site_long_name Long name of the site
14+
#' @param site_url Entry point to query website
15+
#' @param site_short_name Short hand value for the site
16+
#' @param keywords Direct search to be relevant
17+
#' @param suffix Specify page load options.
18+
#'
19+
#' @return
20+
#' A named `list`.
21+
#'
22+
#' @examples
23+
#' # Create a portal to google
24+
#' site_entry("google", "https://github.com/search?q=")
25+
#'
26+
#' # Create a portal to duckduckgo
27+
#' site_entry("duckduckgo", "https://duckduckgo.com/?q=", "ddg")
28+
#'
29+
#' @noRd
30+
site_entry = function(site_long_name,
31+
site_url,
32+
site_short_name = site_long_name,
33+
keywords = keyword_default(),
34+
suffix = NULL) {
35+
list(
36+
"site_long_name" = site_long_name,
37+
"site_short_name" = site_short_name,
38+
"site_url" = site_url,
39+
"keywords" = keywords,
40+
"suffix" = suffix
41+
)
42+
}
43+
44+
site_index =
45+
list(
46+
site_entry("google", "https://google.com/search?q="),
47+
site_entry("bing", "https://bing.com/search?q="),
48+
site_entry("duckduckgo", "https://duckduckgo.com/?q=", "ddg"),
49+
site_entry("startpage", "https://startpage.com/do/dsearch?query=", "sp"),
50+
site_entry(
51+
"stackoverflow",
52+
"https://stackoverflow.com/search?q=",
53+
"so",
54+
keyword_entry("[r]", "[tidyverse]")
55+
),
56+
site_entry(
57+
"rstudio community",
58+
"https://community.rstudio.com/search?q=",
59+
"rscom",
60+
NULL
61+
),
62+
site_entry(
63+
"github",
64+
"https://github.com/search?q=",
65+
"gh",
66+
keyword_entry("language:r type:issue"),
67+
"&type=Issues"
68+
),
69+
site_entry(
70+
"bitbucket",
71+
"https://bitbucket.com/search?q=",
72+
"bb",
73+
keyword_entry("lang:r")
74+
)
75+
)
76+
77+
site_name_matrix = function() {
78+
cbind(vapply(site_index, "[[", "", "site_long_name"),
79+
vapply(site_index, "[[", "", "site_short_name"))
80+
}
81+
82+
site_details = function(site) {
83+
site_names = site_name_matrix()
84+
85+
idx = which(site_names == tolower(site), arr.ind = TRUE)
86+
87+
# If empty, not found.
88+
if ( nrow(idx) == 0L ) {
89+
stop("`site` must be a valid site name.", call. = FALSE)
90+
}
91+
92+
# Retrieve the first row position
93+
site_index[[ idx[1, 1] ]]
94+
}
95+
96+

R/search-functions.R

Lines changed: 22 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
#' `"google"` (default), `"bing"`, `"duckduckgo"`, `"startpage"`,
88
#' `"stackoverflow"`, `"rstudio community"`, `"github"`, and
99
#' `"bitbucket"`.
10-
#' @param query Contents of string to search. Default is the error message.
11-
#' @param rlang Search for results written in R. Default is `TRUE`
10+
#' @param query Contents of string to search. Default is the error message.
11+
#' @param rlang Search for results written in R. Default is `TRUE`
1212
#'
1313
#' @return The generated search URL or an empty string.
1414
#'
@@ -124,16 +124,23 @@ search_site = function(query,
124124
#' # On error, automatically search the message on google
125125
#' options(error = searcher("google"))
126126
#' }
127-
searcher = function(site, rlang = TRUE, keyword = getOption("searcher.default_keyword", "base")) {
127+
searcher = function(site, keyword = getOption("searcher.default_keyword")) {
128128

129-
check_valid_site(site)
129+
entry = site_details(site)
130130

131-
function(query = geterrmessage(), rlang = rlang) {
132-
search_site(query, site, rlang = rlang)
131+
function(query = geterrmessage(), rlang = TRUE) {
132+
133+
if (!valid_query(query)) {
134+
message("`query` must contain only 1 element that is not empty.")
135+
return(invisible(""))
136+
}
137+
138+
query = append_search_term_suffix(query, rlang, entry[["keywords"]][[keyword]])
139+
140+
browse_url(entry$site_url, query, entry$suffix)
133141
}
134142
}
135143

136-
137144
########################### Start Search Engines
138145

139146
#' @rdname search_site
@@ -144,48 +151,21 @@ searcher = function(site, rlang = TRUE, keyword = getOption("searcher.default_ke
144151
#'
145152
#' See \url{https://moz.com/blog/the-ultimate-guide-to-the-google-search-parameters}
146153
#' for details.
147-
search_google = function(query = geterrmessage(), rlang = TRUE) {
148-
if (!valid_query(query)) {
149-
message("Please provide only 1 `query` term that is not empty.")
150-
return(invisible(""))
151-
}
152-
153-
query = append_r_suffix(query, rlang = rlang)
154-
155-
browse_url("https://google.com/search?q=", query)
156-
}
154+
search_google = searcher("google")
157155

158156
#' @rdname search_site
159157
#' @export
160158
#' @section Bing Search:
161159
#' The `search_bing()` function searches [Bing](https://bing.com) using:
162160
#' `https://bing.com/search?q=<query>`
163-
search_bing = function(query = geterrmessage(), rlang = TRUE) {
164-
if (!valid_query(query)) {
165-
message("Please provide only 1 `query` term that is not empty.")
166-
return(invisible(""))
167-
}
168-
169-
query = append_r_suffix(query, rlang = rlang)
170-
171-
browse_url("https://bing.com/search?q=", query)
172-
}
161+
search_bing = searcher("bing")
173162

174163
#' @rdname search_site
175164
#' @export
176165
#' @section DuckDuckGo Search:
177166
#' The `search_duckduckgo()` and `search_ddg()` functions both search
178167
#' [DuckDuckGo](https://duckduckgo.com) using: `https://duckduckgo.com/?q=<query>`
179-
search_duckduckgo = function(query = geterrmessage(), rlang = TRUE) {
180-
if (!valid_query(query)) {
181-
message("Please provide only 1 `query` term that is not empty.")
182-
return(invisible(""))
183-
}
184-
185-
query = append_r_suffix(query, rlang = rlang)
186-
187-
browse_url("https://duckduckgo.com/?q=", query)
188-
}
168+
search_duckduckgo = searcher("ddg")
189169

190170
#' @rdname search_site
191171
#' @export
@@ -208,16 +188,7 @@ search_ixquick = function(query = geterrmessage(), rlang = TRUE) {
208188
#' For additional details regarding [startpage](https://startpage.com)'s
209189
#' search interface please see:
210190
#' \url{https://support.startpage.com/index.php?/Knowledgebase/Article/View/1261/0/add-familystartpagecom-as-the-default-search-engine-in-chrome}
211-
search_startpage = function(query = geterrmessage(), rlang = TRUE) {
212-
if (!valid_query(query)) {
213-
message("Please provide only 1 `query` term that is not empty.")
214-
return(invisible(""))
215-
}
216-
217-
query = append_r_suffix(query, rlang = rlang)
218-
219-
browse_url("https://startpage.com/do/dsearch?query=", query)
220-
}
191+
search_startpage = searcher("sp")
221192

222193
#' @rdname search_site
223194
#' @export
@@ -238,16 +209,7 @@ search_sp = search_startpage
238209
#' For additional details regarding [StackOverflow](https://stackoverflow.com)'s
239210
#' search interface please see:
240211
#' \url{https://stackoverflow.com/help/advanced-search-parameters-jobs}
241-
search_stackoverflow = function(query = geterrmessage(), rlang = TRUE) {
242-
if (!valid_query(query)) {
243-
message("Please provide only 1 `query` term that is not empty.")
244-
return(invisible(""))
245-
}
246-
247-
query = append_r_suffix(query, rlang = rlang, "[r]")
248-
249-
browse_url("https://stackoverflow.com/search?q=", query)
250-
}
212+
search_stackoverflow = searcher("so")
251213

252214
#' @rdname search_site
253215
#' @export
@@ -263,17 +225,7 @@ search_so = search_stackoverflow
263225
#' For additional details regarding [RStudio Community](https://community.rstudio.com/)'s
264226
#' search interface please see the [Discourse](https://discourse.org) API documentation:
265227
#' \url{https://docs.discourse.org/#tag/Search}
266-
search_rstudio_community = function(query = geterrmessage(), rlang = TRUE) {
267-
if (!valid_query(query)) {
268-
message("Please provide only 1 `query` term that is not empty.")
269-
return(invisible(""))
270-
}
271-
272-
# Disable using a query check
273-
# query = append_r_suffix(query, rlang = rlang, "[r]")
274-
275-
browse_url("https://community.rstudio.com/search?q=", query)
276-
}
228+
search_rstudio_community = searcher("rscom")
277229

278230
#' @rdname search_site
279231
#' @export
@@ -294,16 +246,7 @@ search_rscom = search_rstudio_community
294246
#' search interface please see:
295247
#' \url{https://help.github.com/categories/searching-for-information-on-github/}
296248
#' and \url{https://help.github.com/articles/searching-code/}
297-
search_github = function(query = geterrmessage(), rlang = TRUE) {
298-
if (!valid_query(query)) {
299-
message("Please provide only 1 `query` term that is not empty.")
300-
return(invisible(""))
301-
}
302-
303-
query = append_r_suffix(query, rlang = rlang, "language:r type:issue")
304-
305-
browse_url("https://github.com/search?q=", query, "&type=Issues")
306-
}
249+
search_github = searcher("gh")
307250

308251
#' @rdname search_site
309252
#' @export
@@ -319,16 +262,7 @@ search_gh = search_github
319262
#' For additional details regarding [BitBucket](https://bitbucket.com)'s
320263
#' search interface please see:
321264
#' \url{https://confluence.atlassian.com/bitbucket/code-search-in-bitbucket-873876782.html}
322-
search_bitbucket = function(query = geterrmessage(), rlang = TRUE) {
323-
if (!valid_query(query)) {
324-
message("Please provide only 1 `query` term that is not empty.")
325-
return(invisible(""))
326-
}
327-
328-
query = append_r_suffix(query, rlang = rlang, "lang:r")
329-
330-
browse_url("https://bitbucket.com/search?q=", query)
331-
}
265+
search_bitbucket = searcher("bb")
332266

333267
#' @rdname search_site
334268
#' @export

R/searcher-environment.R

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)