plotcli-py 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. CLAUDE.md +51 -0
  2. LICENSE +21 -0
  3. PKG-INFO +358 -0
  4. README.md +340 -0
  5. main.py +6 -0
  6. plotcli-original/.Rbuildignore +18 -0
  7. plotcli-original/.github/workflows/deploy_docs.yml +43 -0
  8. plotcli-original/.gitignore +46 -0
  9. plotcli-original/DESCRIPTION +25 -0
  10. plotcli-original/NAMESPACE +60 -0
  11. plotcli-original/NEWS.md +112 -0
  12. plotcli-original/R/ascii_escape.r +13 -0
  13. plotcli-original/R/canvas.r +586 -0
  14. plotcli-original/R/class_functions.r +114 -0
  15. plotcli-original/R/geom_registry.r +1376 -0
  16. plotcli-original/R/ggplotcli.r +234 -0
  17. plotcli-original/R/ggplotcli_helpers.r +1099 -0
  18. plotcli-original/R/helper_functions.r +351 -0
  19. plotcli-original/R/plotcli.r +963 -0
  20. plotcli-original/R/plotcli_grid.r +1 -0
  21. plotcli-original/R/plotcli_wrappers.r +416 -0
  22. plotcli-original/R/zzz.r +15 -0
  23. plotcli-original/README.md +192 -0
  24. plotcli-original/docs/ascii.png +0 -0
  25. plotcli-original/docs/bar.png +0 -0
  26. plotcli-original/docs/block.png +0 -0
  27. plotcli-original/docs/boxplot.png +0 -0
  28. plotcli-original/docs/density.png +0 -0
  29. plotcli-original/docs/facet.png +0 -0
  30. plotcli-original/docs/facet_grid.png +0 -0
  31. plotcli-original/docs/generate_png.sh +137 -0
  32. plotcli-original/docs/heatmap.png +0 -0
  33. plotcli-original/docs/histogram.png +0 -0
  34. plotcli-original/docs/line.png +0 -0
  35. plotcli-original/docs/noborder.png +0 -0
  36. plotcli-original/docs/scatter.png +0 -0
  37. plotcli-original/docs/showcase.R +182 -0
  38. plotcli-original/inst/doc/ggplotcli.R +231 -0
  39. plotcli-original/inst/doc/ggplotcli.Rmd +329 -0
  40. plotcli-original/inst/doc/ggplotcli.html +1078 -0
  41. plotcli-original/inst/doc/plotcli_class.R +98 -0
  42. plotcli-original/inst/doc/plotcli_class.Rmd +121 -0
  43. plotcli-original/inst/doc/plotcli_class.html +564 -0
  44. plotcli-original/inst/doc/plotcli_wrappers.R +35 -0
  45. plotcli-original/inst/doc/plotcli_wrappers.Rmd +62 -0
  46. plotcli-original/inst/doc/plotcli_wrappers.html +546 -0
  47. plotcli-original/man/AsciiCanvas.Rd +116 -0
  48. plotcli-original/man/BlockCanvas.Rd +132 -0
  49. plotcli-original/man/BrailleCanvas.Rd +146 -0
  50. plotcli-original/man/Canvas.Rd +492 -0
  51. plotcli-original/man/GeomRegistry.Rd +9 -0
  52. plotcli-original/man/add_legend_to_output.Rd +12 -0
  53. plotcli-original/man/braille_dot_bit.Rd +29 -0
  54. plotcli-original/man/braille_set_dot.Rd +21 -0
  55. plotcli-original/man/bresenham.Rd +27 -0
  56. plotcli-original/man/build_plot_output.Rd +28 -0
  57. plotcli-original/man/build_plot_output_v2.Rd +41 -0
  58. plotcli-original/man/cat_plot_matrix.Rd +17 -0
  59. plotcli-original/man/cbind.plotcli.Rd +19 -0
  60. plotcli-original/man/cbind_plots.Rd +17 -0
  61. plotcli-original/man/color_to_term.Rd +18 -0
  62. plotcli-original/man/create_canvas.Rd +21 -0
  63. plotcli-original/man/create_panel_scales.Rd +29 -0
  64. plotcli-original/man/create_scales.Rd +27 -0
  65. plotcli-original/man/dot-geom_registry.Rd +16 -0
  66. plotcli-original/man/draw_border.Rd +12 -0
  67. plotcli-original/man/draw_grid.Rd +12 -0
  68. plotcli-original/man/extract_legend_info.Rd +12 -0
  69. plotcli-original/man/extract_plot_labels.Rd +12 -0
  70. plotcli-original/man/extract_plot_style.Rd +12 -0
  71. plotcli-original/man/format_axis_label.Rd +18 -0
  72. plotcli-original/man/format_four_chars.Rd +21 -0
  73. plotcli-original/man/geom_area_handler.Rd +12 -0
  74. plotcli-original/man/geom_bar_handler.Rd +12 -0
  75. plotcli-original/man/geom_boxplot_handler.Rd +13 -0
  76. plotcli-original/man/geom_density_handler.Rd +12 -0
  77. plotcli-original/man/geom_histogram_handler.Rd +12 -0
  78. plotcli-original/man/geom_hline_handler.Rd +12 -0
  79. plotcli-original/man/geom_line_handler.Rd +12 -0
  80. plotcli-original/man/geom_path_handler.Rd +12 -0
  81. plotcli-original/man/geom_point_handler.Rd +12 -0
  82. plotcli-original/man/geom_rect_handler.Rd +12 -0
  83. plotcli-original/man/geom_segment_handler.Rd +12 -0
  84. plotcli-original/man/geom_smooth_handler.Rd +12 -0
  85. plotcli-original/man/geom_text_handler.Rd +12 -0
  86. plotcli-original/man/geom_vline_handler.Rd +12 -0
  87. plotcli-original/man/get_color_hue.Rd +18 -0
  88. plotcli-original/man/get_data_subset.Rd +23 -0
  89. plotcli-original/man/get_facet_info.Rd +18 -0
  90. plotcli-original/man/get_geom_handler.Rd +17 -0
  91. plotcli-original/man/get_term_colors.Rd +21 -0
  92. plotcli-original/man/ggplotcli.Rd +83 -0
  93. plotcli-original/man/init_color_mapping.Rd +15 -0
  94. plotcli-original/man/is_braille.Rd +20 -0
  95. plotcli-original/man/is_geom_registered.Rd +17 -0
  96. plotcli-original/man/list_registered_geoms.Rd +14 -0
  97. plotcli-original/man/make_colored.Rd +23 -0
  98. plotcli-original/man/make_unique_names.Rd +20 -0
  99. plotcli-original/man/normalize_data.Rd +27 -0
  100. plotcli-original/man/pclib.Rd +48 -0
  101. plotcli-original/man/pclibx.Rd +46 -0
  102. plotcli-original/man/pclid.Rd +44 -0
  103. plotcli-original/man/pclih.Rd +50 -0
  104. plotcli-original/man/pclil.Rd +48 -0
  105. plotcli-original/man/pclis.Rd +48 -0
  106. plotcli-original/man/pixel_to_braille.Rd +23 -0
  107. plotcli-original/man/plotcli.Rd +598 -0
  108. plotcli-original/man/plotcli_bar.Rd +48 -0
  109. plotcli-original/man/plotcli_box.Rd +46 -0
  110. plotcli-original/man/plotcli_density.Rd +44 -0
  111. plotcli-original/man/plotcli_histogram.Rd +50 -0
  112. plotcli-original/man/plotcli_line.Rd +48 -0
  113. plotcli-original/man/plotcli_options.Rd +18 -0
  114. plotcli-original/man/plotcli_scatter.Rd +48 -0
  115. plotcli-original/man/plus-.plotcli.Rd +19 -0
  116. plotcli-original/man/rbind.plotcli.Rd +19 -0
  117. plotcli-original/man/rbind_plots.Rd +17 -0
  118. plotcli-original/man/register_geom.Rd +21 -0
  119. plotcli-original/man/remove_color_codes.Rd +21 -0
  120. plotcli-original/man/render_faceted_plot.Rd +25 -0
  121. plotcli-original/man/render_single_panel.Rd +12 -0
  122. plotcli-original/man/safe_aes_name.Rd +18 -0
  123. plotcli-original/tests/testthat/test-new-geoms.R +136 -0
  124. plotcli-original/tests/testthat/test-plotcli.R +69 -0
  125. plotcli-original/tests/testthat.R +4 -0
  126. plotcli-original/vignettes/ggplotcli.Rmd +329 -0
  127. plotcli-original/vignettes/plotcli_class.R +98 -0
  128. plotcli-original/vignettes/plotcli_class.Rmd +121 -0
  129. plotcli-original/vignettes/plotcli_wrappers.R +35 -0
  130. plotcli-original/vignettes/plotcli_wrappers.Rmd +62 -0
  131. plotcli.egg-info/PKG-INFO +11 -0
  132. plotcli.egg-info/SOURCES.txt +7 -0
  133. plotcli.egg-info/dependency_links.txt +1 -0
  134. plotcli.egg-info/entry_points.txt +3 -0
  135. plotcli.egg-info/top_level.txt +1 -0
  136. plotcli.py +978 -0
  137. plotcli_py-0.1.0.dist-info/METADATA +358 -0
  138. plotcli_py-0.1.0.dist-info/RECORD +143 -0
  139. plotcli_py-0.1.0.dist-info/WHEEL +4 -0
  140. plotcli_py-0.1.0.dist-info/entry_points.txt +2 -0
  141. plotcli_py-0.1.0.dist-info/licenses/LICENSE +21 -0
  142. pyproject.toml +31 -0
  143. uv.lock +8 -0
@@ -0,0 +1,234 @@
1
+ #' Get data subset for a specific geom
2
+ #'
3
+ #' This function returns a subset of the data for a specific geom.
4
+ #'
5
+ #' @param geom_name The name of the geom for which the data subset is needed.
6
+ #' @param data The data to be subsetted.
7
+ #' @param aes The aesthetic mappings for the geom.
8
+ #' @param p_build The ggplot build object.
9
+ #' @return A list containing the data subset for the specified geom.
10
+ #' @export
11
+ get_data_subset <- function(geom_name, data, aes, p_build) {
12
+
13
+ out = data
14
+
15
+ if (geom_name == "GeomDensity") {
16
+ density_data <- density(data[[rlang::as_name(aes$x)]])
17
+ out = list(x = density_data$x, y = density_data$y)
18
+ }
19
+
20
+ if(geom_name == "GeomSmooth") out =list(x = p_build$data[[2]]$x, y = p_build$data[[2]]$y)
21
+
22
+ if(geom_name %in% c("GeomBoxplot")) {
23
+
24
+ out$y = data[[rlang::as_name(aes$x)]]
25
+ out$x = rep(1, length(out$y))
26
+
27
+ }
28
+
29
+ if(!geom_name %in% c("GeomDensity", "GeomSmooth", "GeomBoxplot", "GeomBar")) {
30
+
31
+ out$x = data[[rlang::as_name(aes$x)]]
32
+ out$y = data[[rlang::as_name(aes$y)]]
33
+
34
+ }
35
+
36
+ return(out)
37
+
38
+ }
39
+
40
+ #' Safely extract aesthetic name from ggplot mapping
41
+ #'
42
+ #' Handles quosures, simple symbols, and calls like factor(cyl)
43
+ #'
44
+ #' @param aes_expr The aesthetic expression (can be a quosure)
45
+ #' @return Character string of the column name, or NULL
46
+ #' @keywords internal
47
+ safe_aes_name <- function(aes_expr) {
48
+ if (is.null(aes_expr)) return(NULL)
49
+
50
+ # If it's a quosure, extract the expression
51
+ if (rlang::is_quosure(aes_expr)) {
52
+ aes_expr <- rlang::quo_get_expr(aes_expr)
53
+ }
54
+
55
+ # If it's a simple symbol, use as_name
56
+ if (rlang::is_symbol(aes_expr)) {
57
+ return(rlang::as_name(aes_expr))
58
+ }
59
+
60
+ # If it's a call (like factor(cyl)), try to extract the first argument
61
+ if (rlang::is_call(aes_expr)) {
62
+ # Get the call arguments
63
+ args <- rlang::call_args(aes_expr)
64
+ if (length(args) > 0) {
65
+ # Recursively try to get the name from the first argument
66
+ return(safe_aes_name(args[[1]]))
67
+ }
68
+ }
69
+
70
+ # Fallback: try to deparse and clean up
71
+ tryCatch({
72
+ # Last resort: deparse the expression
73
+ deparsed <- deparse(aes_expr)
74
+ # Try to extract column name from factor(col) or similar
75
+ if (grepl("^\\w+\\((.+)\\)$", deparsed)) {
76
+ return(gsub("^\\w+\\((.+)\\)$", "\\1", deparsed))
77
+ }
78
+ return(deparsed)
79
+ }, error = function(e) {
80
+ return(NULL)
81
+ })
82
+ }
83
+
84
+ #' ggplotcli - Render ggplot2 objects in the terminal
85
+ #'
86
+ #' Convert any ggplot2 plot to a terminal-based visualization using Unicode
87
+ #' Braille characters or ASCII. Supports 15+ geom types, faceting, themes,
88
+ #' and color aesthetics.
89
+ #'
90
+ #' @param p A ggplot2 object to render
91
+ #' @param width Character width of the plot (default: 60)
92
+ #' @param height Character height of the plot (default: 20)
93
+ #' @param canvas_type Type of canvas: "braille" (high-res), "block" (medium), or "ascii" (basic). Default: "braille"
94
+ #' @param border Draw border around plot. "auto" uses ggplot theme, or TRUE/FALSE (default: "auto")
95
+ #' @param grid Grid lines: "none", "major", "minor", "both", or "auto" (default: "none")
96
+ #' @param show_axes Whether to show axis values (default: TRUE)
97
+ #' @param axis_labels Whether to show axis labels from ggplot (default: TRUE)
98
+ #' @param legend Legend display: "auto", "right", "bottom", "none" (default: "auto")
99
+ #' @param title_align Title alignment: "center" or "left" (default: "center")
100
+ #' @param subtitle Whether to show subtitle (default: TRUE)
101
+ #' @param caption Whether to show caption (default: TRUE)
102
+ #' @param title Optional title override (NULL uses ggplot title)
103
+ #' @param boxplot_style Style for boxplots: "ascii" uses box-drawing characters (default),
104
+ #' "braille" uses Braille dots like other geoms
105
+ #'
106
+ #' @return Invisibly returns the canvas object
107
+ #' @export
108
+ #'
109
+ #' @examples
110
+ #' library(ggplot2)
111
+ #'
112
+ #' # Basic scatter plot
113
+ #' p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
114
+ #' ggplotcli(p)
115
+ #'
116
+ #' # With styling
117
+ #' ggplotcli(p, border = TRUE, grid = "major")
118
+ #'
119
+ #' # Faceted plot
120
+ #' p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
121
+ #' geom_point() +
122
+ #' facet_wrap(~cyl)
123
+ #' ggplotcli(p, width = 70, height = 16)
124
+ #'
125
+ #' # Multiple geoms
126
+ #' p <- ggplot(mtcars, aes(x = mpg)) +
127
+ #' geom_histogram(aes(y = after_stat(density)), bins = 10) +
128
+ #' geom_density(color = "red")
129
+ #' ggplotcli(p)
130
+ ggplotcli <- function(p,
131
+ width = 60,
132
+ height = 20,
133
+ canvas_type = "braille",
134
+ border = "auto",
135
+ grid = "none",
136
+ show_axes = TRUE,
137
+ axis_labels = TRUE,
138
+ legend = "auto",
139
+ title_align = "center",
140
+ subtitle = TRUE,
141
+ caption = TRUE,
142
+ title = NULL,
143
+ boxplot_style = "ascii") {
144
+
145
+ # Build the plot to get computed data
146
+ built <- ggplot2::ggplot_build(p)
147
+
148
+ # Initialize color mapping for all colors in the plot (including legend colors)
149
+ # This ensures we minimize color repetition across groups and consistent legend
150
+ all_colors <- c()
151
+ for (layer_data in built$data) {
152
+ if ("colour" %in% names(layer_data)) {
153
+ all_colors <- c(all_colors, layer_data$colour)
154
+ }
155
+ if ("fill" %in% names(layer_data)) {
156
+ all_colors <- c(all_colors, layer_data$fill)
157
+ }
158
+ }
159
+
160
+ # Also include legend colors for consistent mapping
161
+ # Helper to extract colors from a scale (handles both discrete and continuous)
162
+ get_scale_colors <- function(scale, n) {
163
+ colors <- tryCatch(scale$palette(n), error = function(e) NULL)
164
+ if (is.null(colors) || (length(colors) == 1 && is.na(colors[1])) ||
165
+ all(is.na(colors))) {
166
+ colors <- tryCatch(scale$palette(seq(0, 1, length.out = n)), error = function(e) NULL)
167
+ }
168
+ colors
169
+ }
170
+
171
+ # Get legend colors from colour scale
172
+ color_scale <- built$plot$scales$get_scales("colour")
173
+ if (!is.null(color_scale)) {
174
+ tryCatch({
175
+ breaks <- color_scale$get_breaks()
176
+ n <- length(breaks)
177
+ if (n > 0) {
178
+ legend_cols <- get_scale_colors(color_scale, n)
179
+ if (!is.null(legend_cols) && !all(is.na(legend_cols))) {
180
+ all_colors <- c(all_colors, legend_cols)
181
+ }
182
+ }
183
+ }, error = function(e) NULL)
184
+ }
185
+
186
+ # Get legend colors from fill scale
187
+ fill_scale <- built$plot$scales$get_scales("fill")
188
+ if (!is.null(fill_scale)) {
189
+ tryCatch({
190
+ breaks <- fill_scale$get_breaks()
191
+ n <- length(breaks)
192
+ if (n > 0) {
193
+ legend_cols <- get_scale_colors(fill_scale, n)
194
+ if (!is.null(legend_cols) && !all(is.na(legend_cols))) {
195
+ all_colors <- c(all_colors, legend_cols)
196
+ }
197
+ }
198
+ }, error = function(e) NULL)
199
+ }
200
+
201
+ init_color_mapping(unique(all_colors))
202
+
203
+ # Extract styling from ggplot theme
204
+ style <- extract_plot_style(built, border, grid, legend)
205
+
206
+ # Get plot labels
207
+ labels <- extract_plot_labels(built, title, subtitle, caption, axis_labels)
208
+
209
+ # Create style options object
210
+ style_opts <- list(
211
+ border = style$border,
212
+ grid = style$grid,
213
+ show_axes = show_axes,
214
+ axis_labels = axis_labels,
215
+ legend = style$legend,
216
+ title_align = title_align,
217
+ labels = labels,
218
+ boxplot_style = boxplot_style
219
+ )
220
+
221
+ # Check for faceting
222
+ layout <- built$layout
223
+
224
+ facet_info <- get_facet_info(layout)
225
+
226
+ if (facet_info$has_facets) {
227
+ # Render faceted plot
228
+ render_faceted_plot(built, facet_info, width, height, canvas_type,
229
+ style_opts)
230
+ } else {
231
+ # Render single panel plot
232
+ render_single_panel(built, width, height, canvas_type, style_opts)
233
+ }
234
+ }