@@ -180,18 +180,41 @@ function(x)
180180 return (x )
181181 }
182182 bib <- R_bibentries()
183- # # <FIXME>
183+ cited <- Rd_expr_bibcite_keys_cited()
184184 # # Would be nice to have a common reader for possibly multi-line
185185 # # comma separated values ...
186- keys <- strsplit(x , " ,[[:space:]]*" )[[1L ]]
187- if (any(keys == " *" )) {
188- keys <- c(keys , Rd_expr_bibcite_keys_cited())
189- Rd_expr_bibcite_keys_cited(NULL )
186+ given <- strsplit(x , " ,[[:space:]]*" )[[1L ]]
187+ if (any(given == " *" ))
188+ given <- c(given [given != " *" ], cited )
189+ Rd_expr_bibcite_keys_cited(setdiff(cited , given ))
190+ y <- sort(unique(bib [.bibentry_get_key(bib ) %in% given ]))
191+ # # Merge bibinfo data.
192+ keys <- .bibentry_get_key(y )
193+ store <- Rd_expr_bibinfo_data_store()
194+ for (k in intersect(keys , names(store ))) {
195+ entry <- store [[k ]]
196+ for (f in names(entry ))
197+ y [k , f ] <- entry [[f ]]
190198 }
191- y <- sort(unique(bib [bib $ key %in% keys ]))
192- paste(sprintf(" \\ if{html}{\u 2060\\ out{<span id=\" reference+%s\" >}}%s\\ if{html}{\\ out{</span>}}" ,
193- string2id(unlist(y $ key , use.names = FALSE )),
194- toRd(y )),
199+ Rd_expr_bibinfo_data_store(store [setdiff(names(store ), keys )])
200+ # # Typically the bibinfo data would give headers or footers, but
201+ # # these only get shown when printing bibenties in citation style,
202+ # # so we have to add them ourselves.
203+ headers <- y [, " header" ]
204+ headers <- unlist(ifelse(vapply(headers , is.null , NA ), " " , headers ),
205+ use.names = FALSE )
206+ if (any(ind <- nzchar(headers )))
207+ headers [ind ] <- paste(headers [ind ], " \\ cr" )
208+ footers <- y [, " footer" ]
209+ footers <- unlist(ifelse(vapply(footers , is.null , NA ), " " , footers ),
210+ use.names = FALSE )
211+ if (any(ind <- nzchar(footers )))
212+ footers [ind ] <- paste(" \\ cr" , footers [ind ])
213+ paste(sprintf(" %s\\ if{html}{\u 2060\\ out{<span id=\" reference+%s\" >}}%s\\ if{html}{\\ out{</span>}}%s" ,
214+ headers ,
215+ string2id(.bibentry_get_key(y )),
216+ toRd(y ),
217+ footers ),
195218 collapse = " \n\n " )
196219}
197220
@@ -210,33 +233,106 @@ function(x, textual = FALSE)
210233{
211234 x <- trimws(x )
212235 bib <- R_bibentries()
213- keys <- strsplit(x , " ,[[:space:]]*" )[[1L ]]
214- # # Allow b<k>a to specify before b and after a.
215- # # Could also use
216- # # regmatches(keys, regexec("(.*<)?(.*)(>.*)?", keys))
217- before <- after <- rep_len(" " , length(keys ))
218- if (any(ind <- grepl(" <" , keys ))) {
219- before [ind ] <- sub(" <.*" , " " , keys [ind ])
220- keys [ind ] <- sub(" .*<" , " " , keys [ind ])
236+ given <- strsplit(x , " ,[[:space:]]*" )[[1L ]]
237+ parts <- strsplit(given , " |" , fixed = TRUE )
238+ parts <- parts [lengths(parts ) %in% c(1L , 3L )]
239+ # # Could complain about the others ...?
240+ keys <- after <- before <- rep_len(" " , length(parts ))
241+ if (any(ind <- (lengths(parts ) == 1L ))) {
242+ keys [ind ] <- unlist(parts [ind ], use.names = FALSE )
221243 }
222- if (any(ind <- grepl(" >" , keys ))) {
223- after [ind ] <- sub(" .*>" , " " , keys [ind ])
224- keys [ind ] <- sub(" >.*" , " " , keys [ind ])
244+ if (any(ind <- (lengths(parts ) == 3L ))) {
245+ keys [ind ] <- vapply(parts , `[` , " " , 2L )
246+ after [ind ] <- vapply(parts , `[` , " " , 3L )
247+ before [ind ] <- vapply(parts , `[` , " " , 1L )
225248 }
226- ind <- keys %in% unlist (bib $ key )
249+ ind <- keys %in% .bibentry_get_key (bib )
227250 if (! all(ind )) {
228- # # <FIXME>
229- # # Should warn about keys not in the bibentries
230- before <- before [ind ]
231- after <- after [ind ]
251+ # # Could complain about keys not in the bibentries ...?
232252 keys <- keys [ind ]
253+ after <- after [ind ]
254+ before <- before [ind ]
255+ }
256+ n <- length(keys )
257+ if (n == 0L )
258+ return (" " )
259+ y <- character (n )
260+ prev <- Rd_expr_bibcite_keys_cited()
261+ if (textual ) {
262+ for (i in seq_len(n )) {
263+ key <- keys [i ]
264+ y [i ] <- utils :: citeNatbib(key , bib [key ], after = after [i ],
265+ previous = prev , textual = TRUE )
266+ prev <- c(prev , key )
267+ }
268+ if (any(ind <- nzchar(before )))
269+ before [ind ] <- paste0(before [ind ], " " )
270+ y <- paste0(before ,
271+ sprintf(" \\ if{html}{\\ out{<a href=\" #reference+%s\" >}}" ,
272+ string2id(keys )),
273+ y ,
274+ rep_len(" \\ if{html}{\\ out{</a>}}" , n ),
275+ collapse = " ; " )
276+ } else {
277+ bibp <- c(" " , " " , " ;" , " a" , " " , " ," )
278+ for (i in seq_len(n )) {
279+ key <- keys [i ]
280+ y [i ] <- utils :: citeNatbib(key , bib [key ],
281+ previous = prev , textual = FALSE ,
282+ bibpunct = bibp )
283+ prev <- c(prev , key )
284+ }
285+ if (any(ind <- nzchar(before )))
286+ before [ind ] <- paste0(before [ind ], " " )
287+ if (any(ind <- nzchar(after )))
288+ after [ind ] <- paste0(" , " , after [ind ])
289+ y <- paste0(" (" ,
290+ paste0(before ,
291+ sprintf(" \\ if{html}{\\ out{<a href=\" #reference+%s\" >}}" ,
292+ string2id(keys )),
293+ y ,
294+ rep_len(" \\ if{html}{\\ out{</a>}}" , n ),
295+ after ,
296+ collapse = " ;" ),
297+ " )" )
233298 }
234299 Rd_expr_bibcite_keys_cited(keys , TRUE )
235- # # <FIXME>
236- # # This really needs a vectorized version of cite() ...
237- before <- sprintf(" \\ if{html}{\\ out{<a href=\" #reference+%s\" >}}%s" ,
238- string2id(keys ), before )
239- after <- sprintf(" %s\\ if{html}{\\ out{</a>}}" , after )
240- utils :: cite(keys , bib , textual , before , after )
300+ y
301+ }
302+
303+ Rd_expr_bibinfo_data_store <- local({
304+ .store <- NULL
305+ function (new , add = FALSE ) {
306+ if (! missing(new )) {
307+ if (add ) {
308+ key <- new [[1L ]]
309+ val <- `names<-`(list (new [[3L ]]), new [[2L ]])
310+ .store [[key ]] <<- c(.store [[key ]], val )
311+ } else
312+ .store <<- new
313+ }
314+ else
315+ .store
316+ }
317+ })
318+
319+ Rd_expr_bibinfo <-
320+ function (key , field , value )
321+ {
322+ Rd_expr_bibinfo_data_store(list (trimws(key ),
323+ trimws(field ),
324+ gsub(" \n\n " , " \n " , trimws(value ))),
325+ add = TRUE )
326+ }
327+
328+ # # utils:::.bibentry_get_key
329+ .bibentry_get_key <-
330+ function (x )
331+ {
332+ if (! length(x ))
333+ return (character ())
334+ keys <- lapply(unclass(x ), attr , " key" )
335+ keys [! lengths(keys )] <- " "
336+ unlist(keys , use.names = FALSE )
241337}
242338
0 commit comments