R/opts.R

Defines functions reset get set

Documented in get reset set

#' Options for the rock package
#'
#' The `rock::opts` object contains three functions to set, get, and reset
#' options used by the rock package. Use `rock::opts$set` to set options,
#' `rock::opts$get` to get options, or `rock::opts$reset` to reset specific or
#' all options to their default values.
#'
#' It is normally not necessary to get or set `rock` options. The defaults implement
#' the Reproducible Open Coding Kit (ROCK) standard, and deviating from these defaults
#' therefore means the processed sources and codes are not compatible and cannot be
#' processed by other software that implements the ROCK. Still, in some cases this
#' degree of customization might be desirable.
#'
#' The following arguments can be passed:
#'
#' \describe{
#'   \item{...}{For `rock::opts$set`, the dots can be used to specify the options
#'   to set, in the format `option = value`, for example, `utteranceMarker = "\n"`. For
#'   `rock::opts$reset`, a list of options to be reset can be passed.}
#'   \item{option}{For `rock::opts$set`, the name of the option to set.}
#'   \item{default}{For `rock::opts$get`, the default value to return if the
#'   option has not been manually specified.}
#'
#' }
#'
#' Some of the options that can be set (see `rock::opts$defaults` for the
#' full list):
#'
#' \describe{
#'   \item{codeRegexes}{A named character vector with one or more regular
#'   expressions that specify how to extract the codes (that were used to code the
#'   sources). These regular expressions *must* each contain one capturing group
#'   to capture the codes.}
#'
#'   \item{idRegexes}{A named character vector with one or more regular
#'   expressions that specify how to extract the different types of
#'   identifiers. These regular expressions *must* each contain one capturing group
#'   to capture the identifiers.}
#'
#'   \item{sectionRegexes}{A named character vector with one or more regular
#'   expressions that specify how to extract the different types of sections.}
#'
#'   \item{autoGenerateIds}{The names of the `idRegexes` that, if missing, should receive
#'   autogenerated identifiers (which consist of 'autogenerated_' followed by an
#'   incrementing number).}
#'
# #'   \item{persistentIds}{The names of the `idRegexes` for the identifiers which, once
# #'   attached to an utterance, should be attached to all following utterances as well (until
# #'   a new identifier with the same name is encountered, after which that identifier will be
# #'   attached to all following utterances, etc).}
#'
#'   \item{noCodes}{This regular expression is matched with all codes after they have been
#'   extracted using the `codeRegexes` regular expression (i.e. they're matched against the
#'   codes themselves without, for example, the square brackets in the default code regex). Any
#'   codes matching this `noCodes` regular expression will be **ignored**, i.e., removed from the
#'   list of codes.}
#'
#'   \item{inductiveCodingHierarchyMarker}{For inductive coding, this marker is used to indicate
#'   hierarchical relationships between codes. The code at the left hand side of this marker will
#'   be considered the parent code of the code on the right hand side. More than two levels
#'   can be specified in one code (for example, if the `inductiveCodingHierarchyMarker` is '>',
#'   the code `grandparent>child>grandchild` would indicate codes at three levels.}
#'
#'   \item{attributeContainers}{The name of YAML fragments containing case attributes (e.g.
#'   metadata, demographic variables, quantitative data about cases, etc).}
#'
#'   \item{codesContainers}{The name of YAML fragments containing (parts of) deductive coding
#'   trees.}
#'
#'   \item{delimiterRegEx}{The regular expression that is used to extract the YAML fragments.}
#'
#'   \item{codeDelimiters}{A character vector of two elements
#' specifying the opening and closing delimiters of codes (conform
#' the default ROCK convention, two square brackets). The square
#' brackets will be escaped; other characters will not, but will
#' be used as-is.}
#'
#'   \item{ignoreRegex}{The regular expression that is used to delete lines before any other
#'   processing. This can be used to enable adding comments to sources, which are then ignored
#'   during analysis.}
#'
#'   \item{includeBootstrap}{Whether to include the default bootstrap CSS.}
#'
#'   \item{utteranceMarker}{How to specify breaks between utterances in the source(s). The
#'   ROCK convention is to use a newline (`\\n`).}
#'
#'   \item{coderId}{A regular expression specifying the coder identifier, specified
#'   similarly to the codeRegexes.}
#'
#'   \item{idForOmittedCoderIds}{The identifier to use for utterances that do not
#'   have a coder id (i.e. utterance that occur in a source that does not specify
#'   a coder id, or above the line where a coder id is specified).}
#'
#' }
#'
#' @aliases opts set get reset
#'
#' @usage opts
#'
#' @examples ### Get the default utteranceMarker
#' rock::opts$get(utteranceMarker);
#'
#' ### Set it to a custom version, so that every line starts with a pipe
#' rock::opts$set(utteranceMarker = "\n|");
#'
#' ### Check that it worked
#' rock::opts$get(utteranceMarker);
#'
#' ### Reset this option to its default value
#' rock::opts$reset(utteranceMarker);
#'
#' ### Check that the reset worked, too
#' rock::opts$get(utteranceMarker);
#'
#' @export
opts <- list();

opts$set <- function(...) {
  dots <- list(...);
  dotNames <- names(dots);
  names(dots) <-
    paste0("rock.", dotNames);
  if (all(dotNames %in% names(opts$defaults))) {
    do.call(options,
            dots);
  } else {
    option <- dotNames;
    stop("Option(s) ", vecTxtQ(option), " is/are not a valid (i.e. existing) option for the rock!");
  }
}

opts$get <- function(option, default=FALSE) {
  option <- as.character(substitute(option));
  if (!option %in% names(opts$defaults)) {
    stop("Option '", option, "' is not a valid (i.e. existing) option for the rock!");
  } else {
    return(getOption(paste0("rock.", option),
                     opts$defaults[[option]]));
  }
}

opts$reset <- function(...) {
  optionNames <-
    unlist(lapply(as.list(substitute(...())),
                  as.character));
  if (length(optionNames) == 0) {
    do.call(opts$set,
            opts$defaults);
  } else {
    prefixedOptionNames <-
      paste0("rock.", optionNames);
    if (all(optionNames %in% names(opts$defaults))) {
      do.call(opts$set,
              opts$defaults[optionNames]);
    } else {
      invalidOptions <-
        !(optionNames %in% names(opts$defaults));
      stop("Option(s) ", vecTxtQ(optionNames[invalidOptions]),
           "' is/are not a valid (i.e. existing) option for the rock!");
    }
  }
}

opts$defaults <-
  list(### Used throughout
       codeRegexes = c(codes = "\\[\\[([a-zA-Z][a-zA-Z0-9_>]*)\\]\\]",
                       ci = "\\[\\[ci--([a-zA-Z0-9_>]+)\\]\\]"),
       idRegexes = c(caseId = "\\[\\[cid[=:]([a-zA-Z0-9_]+)\\]\\]",
                     coderId = "\\[\\[coderId[=:]([a-zA-Z0-9_]+)\\]\\]",
                     stanzaId = "\\[\\[sid[=:]([a-zA-Z0-9_]+)\\]\\]",
                     itemId = "\\[\\[uiid[=:]([a-zA-Z0-9_]+)\\]\\]",
                     probeId = "\\[\\[prbid[=:]([a-zA-Z0-9_]+)\\]\\]",
                     metaqId = "\\[\\[mqid[=:]([a-zA-Z0-9_]+)\\]\\]"#,
                     #sourceId = "\\[\\[sourceId[=:]([a-zA-Z0-9_]+)\\]\\]",
                     #streamId = "\\[\\[streamId[=:]([a-zA-Z0-9_]+)\\]\\]"
                     ),
       ### Introduced in v. 0.6.0 when introducing generic class
       ### instance identifiers (end removing the specified ones,
       ### introducing the below option to copy over column names)
       ciid_columnsToCopy = c(cid = 'caseId',
                              sid = 'stanzaId',
                              uuid = 'itemId',
                              prbid = 'probeId',
                              mqid = 'metaqid'),
       classInstanceRegex = "\\[\\[(?!uid)(?!UID)([a-zA-Z][a-zA-Z0-9_]*)[=:]([a-zA-Z0-9_]+)\\]\\]",
       codeValueRegexes = c(codeValues = "\\[\\[([a-zA-Z0-9_>]+)\\|\\|([a-zA-Z0-9.,_: ?!-]+)\\]\\]"),
       networkCodeRegexes = c(network = "\\[\\[([a-zA-Z][a-zA-Z0-9_>]*)->([a-zA-Z][a-zA-Z0-9_>]*)\\|\\|([a-zA-Z][a-zA-Z0-9_>]*)(\\|\\|[a-zA-Z0-9_>]*)?\\]\\]"),
       networkCodeRegexOrder = c("from", "to", "type", "weight"),
       sectionRegexes = c(sectionBreak = "---<<([a-zA-Z][a-zA-Z0-9_]*)>>---"),
       uidRegex = "\\[\\[uid[=:]([a-zA-Z0-9_]+)\\]\\]",
       inductiveCodingHierarchyMarker = ">",
       codeTreeMarker = ">",
       anchorRegex = "--\\+-\\{([a-zA-Z0-9_:.,+@!#$%^&*)(\\/\\\\>< |~=-]+)\\}-\\+--",

       ### Regular expression describing the characters that can be used for
       ### code identifiers (has to include `inductiveCodingHierarchyMarker`
       ### and `codeTreeMarker`).
       validCodeCharacters = "[a-zA-Z0-9_>]",

       ### Used to parse sources
       autoGenerateIds = c('stanzaId'),
       # persistentIds = c('caseId', 'coderId', 'stanzaId', 'itemId', 'probeId', 'metaqId'),
       persistentIds = c('caseId'),

       sourceId = "sourceId",
       streamId = "streamId",
       anchorsCol = "anchors",

       colNameGlue = "_",

       ### In version 0.6, this was made redundant, except for UIDs
       noCodes = "^uid[=:]", # "^uid[=:]|^dct[=:]|^ci[=:]|^uiid[=:]|^prbid[=:]",

       attributeContainers = c("ROCK_attributes"),
       networkContainers = c("ROCK_network"),
       aestheticContainers = c("ROCK_aesthetics", "ROCK_network"),
       codesContainers = c("ROCK_codes", "codes", "dct"),
       sectionBreakContainers = c("ROCK_sectionBreaks", "section_breaks"),
       delimiterString = "---",
       delimiterRegEx = "^---$",
       ignoreRegex = "^#",
       ignoreOddDelimiters = FALSE,

       ### Network settings
       networkEdgeWeights = "manual",
       networkDefaultEdgeWeight = 1,
       networkCodeCleaningRegexes = c("\\|\\|", ""),
       networkCollapseEdges = TRUE,

       ### Used to merge sources
       coderId = "\\[\\[coderId[=:]([a-zA-Z0-9_]+)\\]\\]",
       idForOmittedCoderIds = "noCoderId",

       ### Whether to warn if a class instance identifier for specified
       ### attributes isn't encountered.
       checkClassInstanceIds = FALSE,

       ### Used for cleaning sources and adding UIDs
       codeDelimiters = c("[[", "]]"),
       uidPrefix = "uid=",
       utteranceMarker = "\n",
       fragmentDelimiter = "\n\n-----\n\n",
       replacementsPre = list(c("([^\\.])(\\.\\.)([^\\.])",
                                "\\1.\\3"),
                              c("([^\\.])(\\.\\.\\.\\.+)([^\\.])",
                                "\\1...\\3"),
                              c("(\\s*\\r?\\n){3,}",
                                "\n"),
                              c("\u2018|\u2019",
                                "'"),
                              c('\u201c|\u201d',
                                '"')),
       replacementsPost = list(c("([^\\,]),([^\\s])",
                                 "\\1, \\2")),
       utteranceSplits = c("([\\?\\!]+\\s?|\u2026\\s?|[[:alnum:]'\"]\\s*\\.(?!\\.\\.)\\s?)"),
       nestingMarker = "~",

       ### Saniziting for DiagrammeR
       diagrammerSanitizing = list(c("\\\"", "`"),
                                   c("\\'", "`"),
                                   c("\\\\", "/"),
                                   c("[^a-zA-Z0-9;)(,._/`-]", " ")),

       ### Used for collecting sources
       utteranceGlue = "\n\n",
       sourceFormatting = "\n\n**Source: `%s`**\n\n",
       codeHeadingFormatting = "%s *(path: %s)*",

       ### Cognitive Interview: Narrative Response Models
       nrm_wsNames = list(
         metadata = "metadata",
         instrument = "instrument",
         probes = "probes",
         stimuli = "stimuli",
         operationalizations = "operationalizations",
         responsemodel_prototype = "responsemodel_prototype",
         responsemodels= "responsemodels"
       ),

       nrm_colNames = list(
         metadata = c(
           metadata_field = 'metadata_field',
           metadata_content = 'metadata_content'
         ),
         instrument = c(
           item_sequence = 'item_sequence',
           item_id = 'item_id',
           item_template_nrm = 'item_template_nrm'
         ),
         probes = c(
           item_id = 'item_id',
           responsemodel_id = 'responsemodel_id',
           stimulus_id = 'stimulus_id',
           probe_id = 'probe_id',
           probe_target = 'probe_target',
           probe_ci_category = 'probe_ci_category',
           probe_ambiguity = 'probe_ambiguity',
           probe_label = 'probe_label'
         ),
         stimuli = c(
           item_id = 'item_id',
           stimulus_id = 'stimulus_id',
           stimulus_content = 'stimulus_content',
           stimulus_language = 'stimulus_language',
           stimulus_function = 'stimulus_function',
           stimulus_alias = 'stimulus_alias'
         ),
         operationalizations = c(
           item_id = 'item_id',
           operationalization_label = 'operationalization_label',
           operationalization_description = 'operationalization_construct',
           operationalization_comments = 'operationalization_comments'
         ),
         responsemodel_prototype = c(
           responsemodel_id = 'responsemodel_id',
           responsemodel_sequence = "responsemodel_sequence",
           responsemodel_label = 'responsemodel_label',
           responsemodel_comments = 'responsemodel_comments'
         ),
         responsemodels = c(
           item_id = 'item_id',
           responsemodel_sequence = "responsemodel_sequence",
           responsemodel_id = 'responsemodel_id',
           responsemodel_label = 'responsemodel_label',
           responsemodel_comments = 'responsemodel_comments'
         )
       ),

       ### For CI template replacements
       ci_template_replacementDelimiters = c("<<", ">>"),
       rpe_mq_idName = "mqid",
       nrm_probe_idName = "prbid",

       uiid_idName = "uiid",
       rpe_iterId = "iterId",
       rpe_batchId = "batchId",
       rpe_popId = "popId",
       rpe_mq_idName = "mqid",
       coderId_name = "coderId",
       caseId_name = "caseId",

       rpe_itemEval_template = "### Coder evaluation

[[eval|| ]]

[[comment||none]]
",

       ### Used for generating html
       codeClass = "code",
       codeValueClass = "codeValue",
       idClass = "identifier",
       sectionClass = "sectionBreak",
       uidClass = "uid",
       utteranceClass = "utterance",
       contextClass = "context",

       ### Regular expressions for Google Sheets
       gSheetId_extractionRegex =
         "^https://docs\\.google\\.com/spreadsheets/d/([a-zA-Z0-9_-]*)(/.*)?$",

       gSheetId_to_exportLink =
         "https://docs.google.com/spreadsheets/d/%s/export?format=xlsx",

       ### When displaying code identifiers, whether to by default show the
       ### full path or just the code identifier itself
       showFullCodePaths = TRUE,

       ### When displaying code paths, whether to by default strip the root
       stripRootsFromCodePaths = TRUE,

       ### For justifications
       justificationFile = "default_justifier_log.jmd",

       ### Used throughout for working with files
       encoding = "UTF-8",
       preventOverwriting = TRUE,
       rlWarn = FALSE, ### Whether to let readLines emit a warning

       ### Whether to include bootstrap CSS when collecting fragments
       includeBootstrap = "smart",

       ### Whether to show table output in the console or viewer,
       ### if shown interactively
       tableOutput = c("viewer", "console"),

       ### color to use for the background when exporting to html
       exportHTMLbackground = "white",

       ### CSS for tableOutput
       tableOutputCSS = paste0("<style>",
                               "p,th,td{font-family:sans-serif}",
                               "td{padding:3px;vertical-align:top;}",
                               "tr:nth-child(even){background-color:#f2f2f2}",
                               "</style>"),

       ### Default heading level
       defaultHeadingLevel = 1,

       theme_codeTreeDiagram =
         list(
           c("layout", "dot", "graph"),
           c("rankdir", "LR", "graph"),
           c("outputorder", "edgesfirst", "graph"),
           c("fixedsize", "false", "node"),
           c("fontname", "arial", "node"),
           c("fontname", "arial", "edge"),
           c("shape", "box", "node"),
           c("style", "rounded,filled", "node"),
           c("color", "#000000", "node"),
           #c("width", "4", "node"),
           c("color", "#888888", "edge"),
           c("dir", "none", "edge"),
           c("headclip", "false", "edge"),
           c("tailclip", "false", "edge"),
           c("fillcolor", "#FFFFFF", "node")
         ),

       theme_utteranceDiagram =
         list(
           c("layout", "dot", "graph"),
           c("rankdir", "LR", "graph"),
           c("outputorder", "edgesfirst", "graph"),
           c("fixedsize", "false", "node"),
           c("fontname", "arial", "node"),
           c("fontname", "arial", "edge"),
           c("shape", "box", "node"),
           c("style", "rounded,filled", "node"),
           c("color", "#000000", "node"),
           c("width", "4", "node"),
           c("color", "#888888", "edge"),
           c("dir", "none", "edge"),
           c("headclip", "false", "edge"),
           c("tailclip", "false", "edge"),
           c("fillcolor", "#FFFFFF", "node")
         ),

       theme_networkDiagram =
         list(
           c("outputorder", "nodesfirst", "graph"),
           c("fixedsize", "false", "node"),
           c("fontname", "arial", "node"),
           c("fontname", "arial", "edge"),
           c("shape", "ellipse", "node"),
           c("style", "rounded,filled", "node"),
           c("color", "#000000", "node"),
           c("color", "#000000", "edge"),
           c("fillcolor", "#FFFFFF", "node")
         ),

       ### Used throughout for debugging
       debug = FALSE,

       ### Used throughout for suppressing messages
       silent = TRUE,

       ### And warnings
       diligentWarnings = TRUE

    );

Try the rock package in your browser

Any scripts or data that you put into this service are public.

rock documentation built on Dec. 28, 2022, 1:55 a.m.