Add new man sections

Change-Id: I7280cb2cf8a939722c4a8c187694e36a0ce216ea
diff --git a/man/apiCall-KorAPConnection-method.Rd b/man/apiCall-KorAPConnection-method.Rd
new file mode 100644
index 0000000..2d0b06e
--- /dev/null
+++ b/man/apiCall-KorAPConnection-method.Rd
@@ -0,0 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPConnection.R
+\name{apiCall,KorAPConnection-method}
+\alias{apiCall,KorAPConnection-method}
+\alias{apiCall}
+\title{Internal API call method}
+\usage{
+\S4method{apiCall}{KorAPConnection}(
+  kco,
+  url,
+  json = TRUE,
+  getHeaders = FALSE,
+  cache = kco@cache,
+  timeout = kco@timeout
+)
+}
+\arguments{
+\item{kco}{KorAPConnection object}
+
+\item{url}{request url}
+
+\item{json}{logical that determines if JSON result is expected}
+
+\item{getHeaders}{logical that determines if headers and content should be returned (as a list)}
+}
+\description{
+Internal API call method
+}
+\keyword{internal}
diff --git a/man/calculate_sophisticated_eta.Rd b/man/calculate_sophisticated_eta.Rd
new file mode 100644
index 0000000..6c4d651
--- /dev/null
+++ b/man/calculate_sophisticated_eta.Rd
@@ -0,0 +1,34 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/logging.R
+\name{calculate_sophisticated_eta}
+\alias{calculate_sophisticated_eta}
+\title{Calculate sophisticated ETA using median of recent non-cached times}
+\usage{
+calculate_sophisticated_eta(
+  individual_times,
+  current_item,
+  total_items,
+  cache_threshold = 0.1,
+  window_size = 5
+)
+}
+\arguments{
+\item{individual_times}{numeric vector of individual item processing times}
+
+\item{current_item}{current item number (1-based)}
+
+\item{total_items}{total number of items to process}
+
+\item{cache_threshold}{minimum time in seconds to consider as non-cached (default: 0.1)}
+
+\item{window_size}{number of recent non-cached times to use for median calculation (default: 5)}
+}
+\value{
+list with eta_seconds, estimated_completion_time, and is_cached flag
+}
+\description{
+Advanced ETA calculation that excludes cached responses and uses median
+of recent timing data for more stable estimates. This is particularly
+useful for operations where some responses may be cached and much faster.
+}
+\keyword{internal}
diff --git a/man/corpusQuery-KorAPConnection-method.Rd b/man/corpusQuery-KorAPConnection-method.Rd
new file mode 100644
index 0000000..d921eb6
--- /dev/null
+++ b/man/corpusQuery-KorAPConnection-method.Rd
@@ -0,0 +1,126 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPQuery.R
+\name{corpusQuery,KorAPConnection-method}
+\alias{corpusQuery,KorAPConnection-method}
+\alias{corpusQuery}
+\title{Search corpus for query terms}
+\usage{
+\S4method{corpusQuery}{KorAPConnection}(
+  kco,
+  query = if (missing(KorAPUrl)) {
+    
+    stop("At least one of the parameters query and KorAPUrl must be specified.", call. =
+    FALSE)
+ } else {
+     httr2::url_parse(KorAPUrl)$query$q
+ },
+  vc = if (missing(KorAPUrl)) "" else httr2::url_parse(KorAPUrl)$query$cq,
+  KorAPUrl,
+  metadataOnly = TRUE,
+  ql = if (missing(KorAPUrl)) "poliqarp" else httr2::url_parse(KorAPUrl)$query$ql,
+  fields = c("corpusSigle", "textSigle", "pubDate", "pubPlace", "availability",
+    "textClass", "snippet", "tokens"),
+  accessRewriteFatal = TRUE,
+  verbose = kco@verbose,
+  expand = length(vc) != length(query),
+  as.df = FALSE,
+  context = NULL
+)
+}
+\arguments{
+\item{kco}{\code{\link[=KorAPConnection]{KorAPConnection()}} object (obtained e.g. from \code{KorAPConnection()}}
+
+\item{query}{string that contains the corpus query. The query language depends on the \code{ql} parameter. Either \code{query} must be provided or \code{KorAPUrl}.}
+
+\item{vc}{string describing the virtual corpus in which the query should be performed. An empty string (default) means the whole corpus, as far as it is license-wise accessible.}
+
+\item{KorAPUrl}{instead of providing the query and vc string parameters, you can also simply copy a KorAP query URL from your browser and use it here (and in \code{KorAPConnection}) to provide all necessary information for the query.}
+
+\item{metadataOnly}{logical that determines whether queries should return only metadata without any snippets. This can also be useful to prevent access rewrites. Note that the default value is TRUE.
+If you want your corpus queries to return not only metadata, but also KWICS, you need to authorize
+your RKorAPClient application as explained in the
+\href{https://github.com/KorAP/RKorAPClient#authorization}{authorization section}
+of the RKorAPClient Readme on GitHub and set the \code{metadataOnly} parameter to
+\code{FALSE}.}
+
+\item{ql}{string to choose the query language (see \href{https://github.com/KorAP/Kustvakt/wiki/Service:-Search-GET#user-content-parameters}{section on Query Parameters} in the Kustvakt-Wiki for possible values.}
+
+\item{fields}{(meta)data fields that will be fetched for every match.}
+
+\item{accessRewriteFatal}{abort if query or given vc had to be rewritten due to insufficient rights (not yet implemented).}
+
+\item{verbose}{print some info}
+
+\item{expand}{logical that decides if \code{query} and \code{vc} parameters are expanded to all of their combinations. Defaults to \code{TRUE}, iff \code{query} and \code{vc} have different lengths}
+
+\item{as.df}{return result as data frame instead of as S4 object?}
+
+\item{context}{string that specifies the size of the left and the right context returned in \code{snippet}
+(provided that \code{metadataOnly} is set to \code{false} and that the necessary access right are  met).
+The format of the context size specifcation (e.g. \verb{3-token,3-token}) is described in the \href{https://github.com/KorAP/Kustvakt/wiki/Service:-Search-GET}{Service: Search GET documentation of the Kustvakt Wiki}.
+If the parameter is not set, the default context size secification of the KorAP server instance will be used.
+Note that you cannot overrule the maximum context size set in the KorAP server instance,
+as this is typically legally motivated.}
+}
+\value{
+Depending on the \code{as.df} parameter, a tibble or a \code{\link[=KorAPQuery]{KorAPQuery()}} object that, among other information, contains the total number of results in \verb{@totalResults}. The resulting object can be used to fetch all query results (with \code{\link[=fetchAll]{fetchAll()}}) or the next page of results (with \code{\link[=fetchNext]{fetchNext()}}).
+A corresponding URL to be used within a web browser is contained in \verb{@webUIRequestUrl}
+Please make sure to check \verb{$collection$rewrites} to see if any unforeseen access rewrites of the query's virtual corpus had to be performed.
+}
+\description{
+\strong{\code{corpusQuery}} performs a corpus query via a connection to a KorAP-API-server
+}
+\examples{
+\dontrun{
+
+# Fetch metadata of every query hit for "Ameisenplage" and show a summary
+KorAPConnection() \%>\%
+  corpusQuery("Ameisenplage") \%>\%
+  fetchAll()
+}
+
+\dontrun{
+
+# Use the copy of a KorAP-web-frontend URL for an API query of "Ameise" in a virtual corpus
+# and show the number of query hits (but don't fetch them).
+
+KorAPConnection(verbose = TRUE) \%>\%
+  corpusQuery(
+    KorAPUrl =
+      "https://korap.ids-mannheim.de/?q=Ameise&cq=pubDate+since+2017&ql=poliqarp"
+  )
+}
+
+\dontrun{
+
+# Plot the time/frequency curve of "Ameisenplage"
+KorAPConnection(verbose = TRUE) \%>\%
+  {
+    . ->> kco
+  } \%>\%
+  corpusQuery("Ameisenplage") \%>\%
+  fetchAll() \%>\%
+  slot("collectedMatches") \%>\%
+  mutate(year = lubridate::year(pubDate)) \%>\%
+  dplyr::select(year) \%>\%
+  group_by(year) \%>\%
+  summarise(Count = dplyr::n()) \%>\%
+  mutate(Freq = mapply(function(f, y) {
+    f / corpusStats(kco, paste("pubDate in", y))@tokens
+  }, Count, year)) \%>\%
+  dplyr::select(-Count) \%>\%
+  complete(year = min(year):max(year), fill = list(Freq = 0)) \%>\%
+  plot(type = "l")
+}
+}
+\references{
+\url{https://ids-pub.bsz-bw.de/frontdoor/index/index/docId/9026}
+}
+\seealso{
+\code{\link[=KorAPConnection]{KorAPConnection()}}, \code{\link[=fetchNext]{fetchNext()}}, \code{\link[=fetchRest]{fetchRest()}}, \code{\link[=fetchAll]{fetchAll()}}, \code{\link[=corpusStats]{corpusStats()}}
+
+Other corpus search functions: 
+\code{\link{fetchAll,KorAPQuery-method}},
+\code{\link{fetchNext,KorAPQuery-method}}
+}
+\concept{corpus search functions}
diff --git a/man/fetchAll-KorAPQuery-method.Rd b/man/fetchAll-KorAPQuery-method.Rd
new file mode 100644
index 0000000..6750192
--- /dev/null
+++ b/man/fetchAll-KorAPQuery-method.Rd
@@ -0,0 +1,43 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPQuery.R
+\name{fetchAll,KorAPQuery-method}
+\alias{fetchAll,KorAPQuery-method}
+\alias{fetchAll}
+\title{Fetch all results of a KorAP query.}
+\usage{
+\S4method{fetchAll}{KorAPQuery}(kqo, verbose = kqo@korapConnection@verbose, ...)
+}
+\description{
+\strong{\code{fetchAll}} fetches all results of a KorAP query.
+}
+\examples{
+\dontrun{
+# Fetch all metadata of every query hit for "Ameisenplage" and show a summary
+q <- KorAPConnection() |>
+  corpusQuery("Ameisenplage") |>
+  fetchAll()
+q@collectedMatches
+
+# Fetch also all KWICs
+q <- KorAPConnection() |> auth() |>
+ corpusQuery("Ameisenplage", metadataOnly = FALSE) |>
+ fetchAll()
+q@collectedMatches
+
+# Retrieve title and text sigle metadata of all texts published on 1958-03-12
+q <- KorAPConnection() |>
+ corpusQuery("<base/s=t>", # this matches each text once
+    vc = "pubDate in 1958-03-12",
+    fields = c("textSigle", "title"),
+) |>
+ fetchAll()
+q@collectedMatches
+}
+
+}
+\seealso{
+Other corpus search functions: 
+\code{\link{corpusQuery,KorAPConnection-method}},
+\code{\link{fetchNext,KorAPQuery-method}}
+}
+\concept{corpus search functions}
diff --git a/man/fetchNext-KorAPQuery-method.Rd b/man/fetchNext-KorAPQuery-method.Rd
new file mode 100644
index 0000000..fc39cb8
--- /dev/null
+++ b/man/fetchNext-KorAPQuery-method.Rd
@@ -0,0 +1,51 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPQuery.R
+\name{fetchNext,KorAPQuery-method}
+\alias{fetchNext,KorAPQuery-method}
+\alias{fetchNext}
+\title{Fetch the next bunch of results of a KorAP query.}
+\usage{
+\S4method{fetchNext}{KorAPQuery}(
+  kqo,
+  offset = kqo@nextStartIndex,
+  maxFetch = maxResultsPerPage,
+  verbose = kqo@korapConnection@verbose,
+  randomizePageOrder = FALSE
+)
+}
+\arguments{
+\item{kqo}{object obtained from \code{\link[=corpusQuery]{corpusQuery()}}}
+
+\item{offset}{start offset for query results to fetch}
+
+\item{maxFetch}{maximum number of query results to fetch}
+
+\item{verbose}{print progress information if true}
+
+\item{randomizePageOrder}{fetch result pages in pseudo random order if true. Use \code{\link[=set.seed]{set.seed()}} to set seed for reproducible results.}
+}
+\value{
+The \code{kqo} input object with updated slots \code{collectedMatches}, \code{apiResponse}, \code{nextStartIndex}, \code{hasMoreMatches}
+}
+\description{
+\strong{\code{fetchNext}} fetches the next bunch of results of a KorAP query.
+}
+\examples{
+\dontrun{
+
+q <- KorAPConnection() \%>\%
+  corpusQuery("Ameisenplage") \%>\%
+  fetchNext()
+q@collectedMatches
+}
+
+}
+\references{
+\url{https://ids-pub.bsz-bw.de/frontdoor/index/index/docId/9026}
+}
+\seealso{
+Other corpus search functions: 
+\code{\link{corpusQuery,KorAPConnection-method}},
+\code{\link{fetchAll,KorAPQuery-method}}
+}
+\concept{corpus search functions}
diff --git a/man/fetchRest-KorAPQuery-method.Rd b/man/fetchRest-KorAPQuery-method.Rd
new file mode 100644
index 0000000..9c4adef
--- /dev/null
+++ b/man/fetchRest-KorAPQuery-method.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPQuery.R
+\name{fetchRest,KorAPQuery-method}
+\alias{fetchRest,KorAPQuery-method}
+\alias{fetchRest}
+\title{Fetches the remaining results of a KorAP query.}
+\usage{
+\S4method{fetchRest}{KorAPQuery}(kqo, verbose = kqo@korapConnection@verbose, ...)
+}
+\description{
+Fetches the remaining results of a KorAP query.
+}
+\examples{
+\dontrun{
+
+q <- KorAPConnection() \%>\%
+  corpusQuery("Ameisenplage") \%>\%
+  fetchRest()
+q@collectedMatches
+}
+
+}
diff --git a/man/format_eta_display.Rd b/man/format_eta_display.Rd
new file mode 100644
index 0000000..95e43e1
--- /dev/null
+++ b/man/format_eta_display.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/logging.R
+\name{format_eta_display}
+\alias{format_eta_display}
+\title{Format ETA information for display}
+\usage{
+format_eta_display(eta_seconds, estimated_completion_time)
+}
+\arguments{
+\item{eta_seconds}{numeric ETA in seconds (can be NA)}
+
+\item{estimated_completion_time}{POSIXct estimated completion time (can be NA)}
+}
+\value{
+character string with formatted ETA or empty string if NA
+}
+\description{
+Helper function to format ETA information consistently across different methods.
+}
+\keyword{internal}
diff --git a/man/get_cache_indicator.Rd b/man/get_cache_indicator.Rd
new file mode 100644
index 0000000..772adf6
--- /dev/null
+++ b/man/get_cache_indicator.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/logging.R
+\name{get_cache_indicator}
+\alias{get_cache_indicator}
+\title{Get cache indicator string}
+\usage{
+get_cache_indicator(is_cached, cache_threshold = 0.1)
+}
+\arguments{
+\item{is_cached}{logical indicating if the item was cached}
+
+\item{cache_threshold}{minimum time threshold for non-cached items}
+}
+\value{
+character string with cache indicator or empty string
+}
+\description{
+Helper function to generate cache indicator for logging.
+}
+\keyword{internal}
diff --git a/man/initialize-KorAPConnection-method.Rd b/man/initialize-KorAPConnection-method.Rd
new file mode 100644
index 0000000..83b05ff
--- /dev/null
+++ b/man/initialize-KorAPConnection-method.Rd
@@ -0,0 +1,113 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPConnection.R
+\name{initialize,KorAPConnection-method}
+\alias{initialize,KorAPConnection-method}
+\title{Initialize KorAPConnection object}
+\usage{
+\S4method{initialize}{KorAPConnection}(
+  .Object,
+  KorAPUrl = if (is.null(Sys.getenv("KORAP_URL")) | Sys.getenv("KORAP_URL") == "") {
+    
+    "https://korap.ids-mannheim.de/"
+ } else {
+     Sys.getenv("KORAP_URL")
+ },
+  apiVersion = "v1.0",
+  apiUrl,
+  accessToken = getAccessToken(KorAPUrl),
+  oauthClient = NULL,
+  oauthScope = "search match_info",
+  authorizationSupported = TRUE,
+  userAgent = "R-KorAP-Client",
+  timeout = 240,
+  verbose = FALSE,
+  cache = TRUE
+)
+}
+\arguments{
+\item{.Object}{KorAPConnection object}
+
+\item{KorAPUrl}{URL of the web user interface of the KorAP server instance you want to access.
+Defaults to the environment variable \code{KORAP_URL} if set and to the IDS Mannheim KorAP main instance
+to query DeReKo, otherwise.}
+
+\item{apiVersion}{which version of KorAP's API you want to connect to.}
+
+\item{apiUrl}{URL of the KorAP web service.}
+
+\item{accessToken}{OAuth2 access token. For queries on corpus parts with restricted
+access (e.g. textual queries on IPR protected data), you need to authorize
+your application with an access token.
+You can obtain an access token in the OAuth settings of your KorAP web interface.
+
+More details are explained in the
+\href{https://github.com/KorAP/RKorAPClient#authorization}{authorization section}
+of the RKorAPClient Readme on GitHub.
+
+To use authorization based on an access token
+in subsequent queries, initialize your KorAP connection with:
+
+\if{html}{\out{<div class="sourceCode">}}\preformatted{kco <- KorAPConnection(accessToken="<access token>")
+}\if{html}{\out{</div>}}
+
+In order to make the API
+token persistent for the currently used \code{KorAPUrl} (you can have one
+token per KorAPUrl / KorAP server instance), use:
+
+\if{html}{\out{<div class="sourceCode">}}\preformatted{persistAccessToken(kco)
+}\if{html}{\out{</div>}}
+
+This will store it in your keyring using the
+\link[keyring:keyring-package]{keyring::keyring-package}. Subsequent KorAPConnection() calls will
+then automatically retrieve the token from your keying. To stop using a
+persisted token, call \code{clearAccessToken(kco)}. Please note that for
+DeReKo, authorized queries will behave differently inside and outside the
+IDS, because of the special license situation. This concerns also cached
+results which do not take into account from where a request was issued. If
+you experience problems or unexpected results, please try \code{kco <- KorAPConnection(cache=FALSE)} or use
+\code{\link[=clearCache]{clearCache()}} to clear the cache completely.
+
+An alternative to using an access token is to use a browser-based oauth2 workflow
+to obtain an access token. This can be done with the \code{\link[=auth]{auth()}} method.}
+
+\item{oauthClient}{OAuth2 client object.}
+
+\item{oauthScope}{OAuth2 scope.}
+
+\item{authorizationSupported}{logical that indicates if authorization is supported/necessary for the current KorAP instance. Automatically set during initialization.}
+
+\item{userAgent}{user agent string.}
+
+\item{timeout}{tineout in seconds for API requests (this does not influence server internal timeouts).}
+
+\item{verbose}{logical that decides whether following operations will default to
+be verbose.}
+
+\item{cache}{logical that decides if API calls are cached locally. You can clear
+the cache with \code{\link[=clearCache]{clearCache()}}.}
+}
+\value{
+\code{\link[=KorAPConnection]{KorAPConnection()}} object that can be used e.g. with
+\code{\link[=corpusQuery]{corpusQuery()}}
+}
+\description{
+Initialize KorAPConnection object
+}
+\examples{
+\dontrun{
+
+kcon <- KorAPConnection(verbose = TRUE)
+kq <- corpusQuery(kcon, "Ameisenplage")
+kq <- fetchAll(kq)
+}
+
+\dontrun{
+
+kcon <- KorAPConnection(verbose = TRUE, accessToken = "e739u6eOzkwADQPdVChxFg")
+kq <- corpusQuery(kcon, "Ameisenplage", metadataOnly = FALSE)
+kq <- fetchAll(kq)
+kq@collectedMatches$snippet
+}
+
+}
+\keyword{internal}
diff --git a/man/initialize-KorAPQuery-method.Rd b/man/initialize-KorAPQuery-method.Rd
new file mode 100644
index 0000000..beb44ad
--- /dev/null
+++ b/man/initialize-KorAPQuery-method.Rd
@@ -0,0 +1,51 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPQuery.R
+\name{initialize,KorAPQuery-method}
+\alias{initialize,KorAPQuery-method}
+\title{Initialize KorAPQuery object}
+\usage{
+\S4method{initialize}{KorAPQuery}(
+  .Object,
+  korapConnection = NULL,
+  request = NULL,
+  vc = "",
+  totalResults = 0,
+  nextStartIndex = 0,
+  fields = c("corpusSigle", "textSigle", "pubDate", "pubPlace", "availability",
+    "textClass", "snippet", "tokens"),
+  requestUrl = "",
+  webUIRequestUrl = "",
+  apiResponse = NULL,
+  hasMoreMatches = FALSE,
+  collectedMatches = NULL
+)
+}
+\arguments{
+\item{.Object}{…}
+
+\item{korapConnection}{KorAPConnection object}
+
+\item{request}{query part of the request URL}
+
+\item{vc}{definition of a virtual corpus}
+
+\item{totalResults}{number of hits the query has yielded}
+
+\item{nextStartIndex}{at what index to start the next fetch of query results}
+
+\item{fields}{what data / metadata fields should be collected}
+
+\item{requestUrl}{complete URL of the API request}
+
+\item{webUIRequestUrl}{URL of a web frontend request corresponding to the API request}
+
+\item{apiResponse}{data-frame representation of the JSON response of the API request}
+
+\item{hasMoreMatches}{logical that signals if more query results can be fetched}
+
+\item{collectedMatches}{matches already fetched from the KorAP-API-server}
+}
+\description{
+Initialize KorAPQuery object
+}
+\keyword{internal}
diff --git a/man/show-KorAPConnection-method.Rd b/man/show-KorAPConnection-method.Rd
new file mode 100644
index 0000000..f690ef3
--- /dev/null
+++ b/man/show-KorAPConnection-method.Rd
@@ -0,0 +1,15 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/KorAPConnection.R
+\name{show,KorAPConnection-method}
+\alias{show,KorAPConnection-method}
+\title{Display KorAPConnection object}
+\usage{
+\S4method{show}{KorAPConnection}(object)
+}
+\arguments{
+\item{object}{KorAPConnection object}
+}
+\description{
+Display KorAPConnection object
+}
+\keyword{internal}