{"id":14067994,"url":"https://github.com/lorenzwalthert/strcode","last_synced_at":"2025-04-22T03:32:24.797Z","repository":{"id":89377151,"uuid":"72376654","full_name":"lorenzwalthert/strcode","owner":"lorenzwalthert","description":"Structure your code better.","archived":false,"fork":false,"pushed_at":"2023-05-08T05:52:54.000Z","size":7294,"stargazers_count":51,"open_issues_count":2,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-01T18:23:43.724Z","etag":null,"topics":["legibility","r","rstudio-addin","structure"],"latest_commit_sha":null,"homepage":"https://lorenzwalthert.github.io/strcode1/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lorenzwalthert.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-30T21:29:00.000Z","updated_at":"2025-02-08T00:42:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"67dc60f9-3dd0-4860-ab92-e51786fb9e08","html_url":"https://github.com/lorenzwalthert/strcode","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzwalthert%2Fstrcode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzwalthert%2Fstrcode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzwalthert%2Fstrcode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzwalthert%2Fstrcode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lorenzwalthert","download_url":"https://codeload.github.com/lorenzwalthert/strcode/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250167610,"owners_count":21386004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["legibility","r","rstudio-addin","structure"],"created_at":"2024-08-13T07:05:53.255Z","updated_at":"2025-04-22T03:32:24.234Z","avatar_url":"https://github.com/lorenzwalthert.png","language":"R","readme":"---\ntitle: \"README\"\noutput: github_document\n---\n\n```{r, echo = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"README-\"\n)\nlibrary(strcode)\n```\n[![Build Status](https://travis-ci.org/lorenzwalthert/strcode.svg?branch=master)](https://travis-ci.org/lorenzwalthert/strcode)\n[![Project Status: WIP ? Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](http://www.repostatus.org/badges/latest/wip.svg)](http://www.repostatus.org/#wip)\n[![CRAN_Status_Badge](http://www.r-pkg.org/badges/version/strcode)](https://cran.r-project.org/package=strcode)\n[![packageversion](https://img.shields.io/badge/Package%20version-0.2.0-orange.svg?style=flat-square)](commits/master)\n\n\n\nThe `strcode` (short for structuring code) package contains tools to organize\nand abstract your code better. It consists of\n\n- An [RStudio Add-in](https://rstudio.github.io/rstudioaddins/) that lets you \n  quickly add code block separators and titles (possibly with unique \n  identifiers) to divide your work into sections.\n  The titles are recognized as sections by RStudio, which enhances the coding\n  experience further.\n- A function `sum_str` that summarizes the code structure based on the \n  separators and their comments added with the Add-in. For one or more files,\n  it can cat the structure to the console or a file.\n- An [RStudio Add-in](https://rstudio.github.io/rstudioaddins/) that lets you\n  insert a code anchor, that is, a hash sequence which can be used to uniquely \n  identify a line in a large code base. \n\n\u003c!-- You can learn more about structuring code in [Bono Usu](https://github.com/lorenzwalthert/bonousu/blob/devel/docs/commenting-code.html), \na guide for good practice in R programming. --\u003e\n\n```{r, out.width = \"650px\", echo = FALSE}\nknitr::include_graphics(\"https://raw.githubusercontent.com/lorenzwalthert/strcode/master/demos/strcode_v0.2.0_video_to_gif2_large.gif\")\n```\n\n\n# Installation\nYou can install the package from GitHub.\n```{r, eval = FALSE}\n# install.packages(\"devtools\")\ndevtools::install_github(\"lorenzwalthert/strcode\")\n```\n\n# Structuring code\nWe suggest three levels of granularity for code structuring, whereas\nhigher-level blocks can contain lower-level blocks.\n\n- level 1 sections, which are high-level blocks that can be \n  separated as follows:\n```{r}\n#   ____________________________________________________________________________\n#   A title                                                                 ####\n```\n\n- level 2 sections, which are medium-level blocks that can be \n  separated as follows:\n```{r}\n##  ............................................................................\n##  A subtitle                                                              ####\n```\n\n- level 3 sections, which are low-level blocks that can be \n  separated as follows:\n```{r}\n### .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . \n### One more                                                                ####\n```\n\n\nYou can notice from the above that\n\n* The number of `#` used in front of the break character (`___`, `...`, `. .`) \n  corresponds to the level of granularity that is separated.\n* The breaks characters `___`, `...`, `. .` were chosen such that they reflect \n  the level of granularity, namely `___` has a much higher visual density than \n  `. .`. \n* Each block has an (optional) short title on what that block is about.\n* Every title ends with `####`. Therefore, the titles are recognized \n  by RStudio as [sections](https://support.rstudio.com/hc/en-us/articles/200484568-Code-Folding-and-Sections).\n  This has the advantages that you can get a quick summary of your code \n  in Rstudio's code pane and you can fold sections as you can fold \n  code or function declarations or if statements. See the pictures below for \n  details.\n  \nThe separators all have length 80. The value is looked up in the global \noption `strcode$char_length` and can therefore be changed by the user.\n\nBy default, breaks and titles are inserted via a Shiny Gadget, but this \ndefault can be overridden by setting the option `strcode$insert_with_shiny` \nto `FALSE` and hence only inserting the break.\n\n# Anchoring sections\nSometimes it is required to refer to a code section, which can be done by title.\nA better way, however, is to use a unique hash sequence - let us call it a \ncode anchor - to create an arguably unique reference to that section. \nA code anchor in `strcode` is enclosed by `#\u003c` and `\u003e#` so all anchors can \nbe found using regular expressions. You can add section breaks \nthat include a hash. That might look like this:\n```{r}\n##  .................. #\u003c 685c967d4e78477623b861d533d0937a \u003e# ..................\n##  An anchored section                                                     ####\n```\n\n# Insert a code anchor\nCode anchors might prove helpful in other situations where one want to anchor a \nsingle line. That is also possible with `strcode`.\nAn example of a code anchor is the following:\n\n```{r, eval=FALSE}\n#\u003c 56f5139874167f4f5635b42c37fd6594 \u003e#\nthis_is_a_super_important_but_hard_to_describe_line_so_let_me_anchor_it\n```\nThe hash sequences in strcode are produced with the R package \n[digest](https://github.com/eddelbuettel/digest).\n\n# Summarizing code\nOnce code has been structured by adding sections (as above), it can easily be \nsummarized or represented in a compact and abstract form. This is particularly \nhandy when the codebase is large, when a lot of people work on the code or when \nnew people join a project. The function `sum_str` is designed for the purpose of \nextracting separators and respective comments, in order to provide high level \ncode summaries. It is highly customizable and flexible, with a host of options. \nThanks to RStudio's API, you can even create summaries of the file you are working on,\nsimply by typing `sum_str()` in the console. The file presented in the example \nsection below can be summarized as follows:\n\n```{r}\nsum_str(path_in = \"placeholder_code/example.R\", \n        file_out = \"\",\n        width = 40,\n        granularity = 2,\n        lowest_sep = FALSE, \n        header = TRUE)\n```\n\n- `path_in` specifies a directory or filenames for looking for content to\n  summarize.\n- `file_out` indicates where to dump the output.\n- `width` gives the width of the output in characters.\n- `granularity = 2`indicates that we want two of three levels of granularity\n  to be contained in the summary and don't include level 3 comments.\n- Similarly, we use `lowest_sep = FALSE` to indicate that we want lowest \n  separators (given `granularity`) to be omitted between the titles of the \n  sections.\n- `header` was set to `TRUE`, so the column names were reported as well. Note \n  that they are slightly off since knitr uses a different tab length. In the R\n  console and more imporantly in the outputed file, they are aliged.\n\n\n## Example of improved legibility\nTo demonstrate the improvement in legibility, we give an extended example with \nsome placeholder code.  \n```{r}\n#   ____________________________________________________________________________\n#   function test                                                           ####\ntest \u003c- function(x) {\n##  ............................................................................\n##  A: pre-processing                                                       ####\n### .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . \n### a: assertive tests                                                      ####\n  # x\n  if(missing(x) || is.null(x)){ \n    x \u003c- character()\n  }\n  assert(\n    # use check within assert\n    check_character(x),\n    check_factor(x),\n    check_numeric(x)\n  )\n  \n  # levels \n  if(!missing(levels)){\n    assert(\n      check_character(levels),\n      check_integer(levels),\n      check_numeric(levels))\n    levels \u003c- na.omit(levels)\n    \n  }\n  \n  # labels\n  if(!missing(labels)){\n    assert(\n      check_character(labels),\n      check_numeric(labels),\n      check_factor(labels)\n      )\n  }\n  \n### .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . \n### b: coercion / remove missing                                            ####\n  x \u003c- as.character(x)\n  uniq_x \u003c- unique(na.omit(x), nmax = nmax)\n  \n### .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . \n### c: warnings                                                             ####\n  \n  if(length(breaks) == 1) {\n    if(breaks \u003e max(x) - min(x) + 1) {\n      stop(\"range too small for the number of breaks specified\")\n    }\n    if(length(x) \u003c= breaks) {\n      warning(\"breaks is a scalar not smaller than the length of x\")\n    }\n  }  \n  \n##  ............................................................................\n##  B: actual function                                                      ####\n   variable \u003c -paste(\"T\", period, \"nog_\", sector, sep = \"\")\n   variable \u003c- paste(variable, \"==\", 1, sep = \"\")\n        \n   arg\u003c-substitute(variable)\n   r\u003c-eval(arg, idlist.data[[1]])\n   a\u003c\u003c-1\n   \n   was_factor \u003c- FALSE\n   if (is.factor(yes)) {\n     yes \u003c- as.character(yes)\n     was_factor \u003c- TRUE\n   } \n   if (is.factor(no)) {\n     no \u003c- as.character(no)\n     was_factor \u003c- TRUE\n   }\n   out \u003c- ifelse(test, yes, no)\n   if(was_factor) {\n     cfactor(out)\n   } else {\n     out\n   } \n   \n##  ............................................................................\n}\n#   ____________________________________________________________________________\n#   function test2                                                          ####\ntest2 \u003c- function(x) {\n##  ............................................................................\n##  A: pre-processing                                                       ####\n### .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . \n### a: assertive tests                                                      ####\n  # x\n  if(missing(x) || is.null(x)){ \n    x \u003c- character()\n  }\n  assert(\n    # use check within assert\n    check_character(x),\n    check_factor(x),\n    check_numeric(x)\n  )\n  \n  # levels \n  if(!missing(levels)){\n    assert(\n      check_character(levels),\n      check_integer(levels),\n      check_numeric(levels))\n    levels \u003c- na.omit(levels)\n    \n  }\n  \n  # labels\n  if(!missing(labels)){\n    assert(\n      check_character(labels),\n      check_numeric(labels),\n      check_factor(labels)\n      )\n  }\n  \n### .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . \n### b: coercion / remove missing                                            ####\n  x \u003c- as.character(x)\n  uniq_x \u003c- unique(na.omit(x), nmax = nmax)\n  \n### .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . \n### c: warnings                                                             ####\n  \n  if(length(breaks) == 1) {\n    if(breaks \u003e max(x) - min(x) + 1) {\n      stop(\"range too small for the number of breaks specified\")\n    }\n    if(length(x) \u003c= breaks) {\n      warning(\"breaks is a scalar not smaller than the length of x\")\n    }\n  }  \n  \n##  ............................................................................\n##  B: actual function                                                      ####\n   variable \u003c -paste(\"T\", period, \"nog_\", sector, sep = \"\")\n   variable \u003c- paste(variable, \"==\", 1, sep = \"\")\n        \n   arg\u003c-substitute(variable)\n   r\u003c-eval(arg, idlist.data[[1]])\n   a\u003c\u003c-1\n   \n   was_factor \u003c- FALSE\n   if (is.factor(yes)) {\n     yes \u003c- as.character(yes)\n     was_factor \u003c- TRUE\n   } \n   if (is.factor(no)) {\n     no \u003c- as.character(no)\n     was_factor \u003c- TRUE\n   }\n   out \u003c- ifelse(test, yes, no)\n   if(was_factor) {\n     cfactor(out)\n   } else {\n     out\n   } \n   \n##  ............................................................................\n}\n```\n","funding_links":[],"categories":["R"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Florenzwalthert%2Fstrcode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Florenzwalthert%2Fstrcode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Florenzwalthert%2Fstrcode/lists"}