2015-10-23 3 views
14

Рассмотрите любую функцию, которая (для rstudio) откроет что-то в средстве просмотра, если y = TRUE и в вашем браузере, если y = FALSE. Вы можете заставить whatever открыть в своем браузере через options(viewer = NULL) (а затем вам нужно выполнить сброс до этого), но я не могу заставить это работать внутри функций, используя обычный подход on.exit. Протестировано на окнах и osx.Принудительное использование rstudio для использования браузера вместо зрителя

f <- function(x, y = TRUE) { 
    if (y) { 
    oo <- getOption('viewer') 
    on.exit(options(viewer = oo)) 
    options(viewer = NULL) 
    } else options(viewer = NULL) 
    print(getOption('viewer')) 
    DT::datatable(x) 
} 

g <- function(x, y = TRUE) { 
    if (y) { 
    oo <- getOption('viewer') 
    on.exit(options(viewer = oo)) 
    options(viewer = NULL) 
    } else options(viewer = NULL) 
    print(getOption('viewer')) 
    htmlTable::htmlTable(x) 
} 

## in rstudio, returns the viewer function 
getOption('viewer') 
# function (url, height = NULL) 
# ... 

## opens in viewer despite `options(viewer = NULL)` 
g(mtcars) 
# NULL 

## again returns the function, ie, reset my options to before g call successfully 
getOption('viewer') 
# function (url, height = NULL) 
# ... 

## opens in browser but leaves `options(viewer = NULL)` after exiting 
g(mtcars, FALSE) 
# NULL 

getOption('viewer') 
# NULL 

Похоже, что зритель не уважает мои варианты в пределах функции среды либо только некоторые HTML (g) или виджет (f). Я думал, что оба будут использовать viewer = NULL внутри функции и возвращать мои параметры так, как они были при выходе, чтобы я мог контролировать, где я хочу посмотреть результат.

Или есть лучший способ сделать это как для html, так и для виджетов? Я пробовал аргумент options в DT::datatable безрезультатно, но это не помогло бы в случае htmlTable::htmlTable.

Единственный другой подход, о котором я могу думать, состоит в том, чтобы написать весь код в файл temp и использовать if (rstudio) rstudio::viewer(tempfile) else browseURL(tempfile), который, я думаю, много работает для чего-то вроде бы столь прямолинейного.

+1

дополнительные очки, если кто-то может смотреть на мою историю изменений и скажите мне, как дифф знает, что я удалил те же символы, двумя различными способами – rawr

+1

я послал вверх «Bat Signal» в Ushey. Надеюсь, он наблюдает за облаками в Сиэтле. – hrbrmstr

ответ

9

Хотя это не исправление, я думаю, что это иллюстрирует, что происходит. Попробуйте добавить Sys.sleep() вызов в on.exit() обработчика:

f <- function(x) { 
    viewer <- getOption("viewer") 
    on.exit({ 
    print("Restoring viewer...") 
    Sys.sleep(3) 
    options(viewer = viewer) 
    }, add = TRUE) 
    options(viewer = NULL) 
    DT::datatable(x) 
} 

## opens in viewer despite `options(viewer = NULL)` 
f(mtcars) 

Вы заметите, что RStudio не «решить», что делать с результатом DT::datatable() вызова до послеon.exit() обработчик закончил выполнение. Это означает, что к тому моменту, когда RStudio хочет понять результат, зритель уже восстановлен! Скорее всего, RStudio ждет, пока R больше не «занят», чтобы решить, как отобразить полученный контент, и к тому времени слишком поздно для временных изменений в опции viewer.

Обратите внимание, что это не объясняет поведение htmlTable. Мое лучшее предположение заключается в том, что происходит какое-то гоночное состояние; потерянная viewer варианта кажется уйти с стратегически расположенными Sys.sleep() звонков ...

К сожалению, работа по всему это означает отказ от использования on.exit() вызова - если мы не можем сообразить, чтобы справиться с этим в RStudio, конечно.

5

Вот один из способов получить эту функциональность, написав код во временный файл и используя browseURL или что угодно.

Суть как f, так и g одинакова, поэтому у вас может быть одна функция для обработки любого типа html-кода или виджета, я полагаю. И, вероятно, виджеты должны быть selfcontained = TRUE.

f <- function(x, y = TRUE) { 
    x <- if ((inherits(x, 'iplot'))) x else DT::datatable(x) 
    if (!y) { 
    htmlFile <- tempfile(fileext = '.html') 
    htmlwidgets::saveWidget(x, htmlFile, selfcontained = TRUE) 
    utils::browseURL(htmlFile) 
    } else x 
} 

g <- function(x, y = TRUE) { 
    x <- htmlTable::htmlTable(x) 
    if (!y) { 
    htmlFile <- tempfile(fileext = '.html') 
    writeLines(x, con = htmlFile) 
    utils::browseURL(htmlFile) 
    } else x 
} 

## opens in viewer 
g(mtcars) 
## opens in browser 
g(mtcars, FALSE) 

## same for widgets 
f(mtcars) 
f(mtcars, FALSE) 

f(qtlcharts::iplot(1:5, 1:5), FALSE) 

## and my options haven't changed 
getOption('viewer') 
# function (url, height = NULL) 
# ... 

Side отметить, что это на самом деле правильный способ иметь htmlTable::htmlTable использовать другой зритель, но g должен работать для любого HTML.

library('htmlTable') 
print(htmlTable(mtcars), useViewer = utils::browseURL) 
Смежные вопросы