UP | HOME |

Evitar la salida truncada de R en emacs

2026-10-12

Evitar el mensaje [TRUNCATED] al evaluar código R en Emacs (ESS)   r emacs ess

Si en emacs con el módulo ESS aparece que las salidas de R están truncadas

+             segmentos <- .Call("C_sacar_se ..." ... [TRUNCATED] 

se puede desactivar dicho comportamiento con estas instrucciones:

## https://emacs.stackexchange.com/questions/69220/ess-turn-off-truncated-in-ess-r-session
library(default) ## Turn off truncated output in emacs
default(.ess.source) <- list(max.deparse.length=1E5)
default(.ess.eval) <- list(max.deparse.length=1E5)

El mensaje .... [TRUNCATED] que aparece en la consola al evaluar bloques largos (como bucles for) proviene del límite visual de R. ESS envía el bloque completo mediante funciones internas, y R corta la visualización para no inundar la pantalla.

Requiere el paquete default de R. Actúa directamente sobre las funciones internas que usa ESS para evaluar el código, dejando intacta la configuración global de R.

Añadir esto a ~/.Rprofile o ejecutarlo en la sesión:

## ~/.Rprofile -- configuracion de R para ESS (Emacs Speaks Statistics)
##
## Objetivo: que la salida del codigo evaluado desde ESS no aparezca truncada
## (".... [TRUNCATED]").
##
## Causa del recorte: al evaluar/enviar codigo, ESS usa las funciones R
## .ess.eval() y .ess.source(), que llaman a source() con max.deparse.length
## (300 por defecto). Toda expresion cuyo deparse supere ese limite se corta.
##
## Solucion original (https://emacs.stackexchange.com/questions/69220):
##   library(default) ## Turn off truncated output in emacs
##   default(.ess.source) <- list(max.deparse.length=1E5)
##   default(.ess.eval) <- list(max.deparse.length=1E5)
##
## No basta escribirlo tal cual aqui: ESS define .ess.source() y .ess.eval()
## al conectar con el proceso R, es decir, DESPUES de leer este fichero, y el
## intento de parche falla porque los objetos todavia no existen. Por eso el
## parche se aplica de forma diferida: un callback de tareas de R lo aplica en
## cuanto ESS carga sus funciones (y lo vuelve a aplicar si ESS recarga ESSR
## dentro de la misma sesion).
##
## Observacion: ESS moderno llama a esas funciones como
## base::as.environment('ESSR')$<funcion>(...), de modo que el parche se copia
## en tres sitios: el entorno de cierre de la funcion (llamadas internas de
## ESSR), el entorno adjunto 'ESSR' (llamadas emitidas por ESS) y .GlobalEnv
## (llamadas por nombre, en versiones antiguas de ESS).
##
## Requisito: paquete 'default' (install.packages("default")).

local({
    if (interactive()) {

        limite <- 1e5
        objetivos <- c(".ess.source", ".ess.eval")
        avisado <- FALSE
        intentos <- 0L

        parchear <- function() {
            for (nm in objetivos) {
                if (!exists(nm, mode = "function", inherits = TRUE)) next
                fun <- get(nm, mode = "function", inherits = TRUE)
                destinos <- list(environment(fun), .GlobalEnv)
                if ("ESSR" %in% search())
                    destinos <- c(destinos, list(as.environment("ESSR")))
                ya <- all(vapply(destinos, function(d)
                    exists(nm, envir = d, inherits = FALSE) &&
                        inherits(get(nm, envir = d, inherits = FALSE),
                                 "defaults_function"),
                    logical(1)))
                if (ya) next                       ## ya parcheada en los tres sitios
                if (!requireNamespace("default", quietly = TRUE)) {
                    if (!avisado) {
                        avisado <<- TRUE
                        message("Rprofile ESS: falta el paquete 'default'; la salida ",
                                "seguira truncada. Instalalo con ",
                                "install.packages(\"default\").")
                    }
                    next
                }
                nueva <- default::`default<-`(fun, list(max.deparse.length = limite))
                for (d in destinos) assign(nm, nueva, envir = d)
            }
            invisible(NULL)
        }

        addTaskCallback(function(...) {
            intentos <<- intentos + 1L
            try(parchear(), silent = TRUE)
            ess.presente <- any(vapply(objetivos, exists, logical(1),
                                       mode = "function", inherits = TRUE))
            ## TRUE mantiene el callback; FALSE lo retira
            !(ess.presente || intentos >= 100L)
        }, name = "ess-sin-truncar")
        invisible(NULL)
    }
})