rshiny module not printing input to output - user-interface

Simple reprex here, but I am trying to print the input as a small test to see if my app is working:
test_ui <- function(id) {
fluidPage(
selectInput("sel_id", "label", 1:10),
textOutput(NS(id, "sel_text"))
)
}
test_server <- function(id) {
moduleServer(
id,
function(input, output, session) {
output$sel_text <- renderText({input$sel_id})
}
)
}
demo <- function() {
ui <- fluidPage(
test_ui("x")
)
server <- function(input, output, session) {
test_server("x")
}
shinyApp(ui, server)
}
demo()
I was expecting the text to print below the input box but all I got was the select box:
I tried substituting the output line with:
output$sel_text <- renderText({"test_text"})
and it printed:
So it must be something to do with the input values. Weirdly enough in my main (more complex) app, writing the code directly into the ui/server files works, so I must be tripping up on some aspect of modules I don't understand. Would greatly appreciate if someone could point out what I am missing.

Silly me! All I forgot was the following call to NS():
selectInput(NS(id, "sel_id"), "label", 1:10)

Related

Testing a Log statement output in Golang

Hi I want to check that the output of a Log.error() is valid, I have this following code here
func logError(param bool)
bool {
if (param == true)
log.Error(fmt.Sprintf("I need to somehow tst, that the output here is correct"))
return param;
}
I am not allowed to modify my existing code, I just want to ensure that whatever is printed by the console by my logError function, is what I expect it to be.
Is this possible without modifying my existing code, thank you.
With logrus, you can capture the output of the logger in a test:
oldOut:=log.StandardLogger().Out // Save current log target
buf:=bytes.Buffer{}
log.SetOutput(&buf)
logError(true)
// Here, buf.String() should give you the log msg
log.SetOutput(oldOut) // Restore log target

Issue with ANSI cursor movement in goroutine

Background
I'm trying to write a Go library for creating terminal task-lists, inspired by the Node library listr.
My library, golist, prints the task list out in a background goroutine and updates the text and status characters using ANSI escape sequences.
The Problem
There's an issue where the final print of the list will occasionally have extra spaces included, leading to some spaces or repeated lines. Here are two examples – one correct, one not – both from runs of the same exact code (here's a link to the code).
Example
Here's an example of what it should look like:
(Here's a gist of the raw text output for the correct output)
And here's an example of what it sometimes looks like:
(Here's a gist of the raw text output for the incorrect output)
If you look at lines 184 and 185 in the gist of the incorrect version, there are two blank lines that aren't in the correct version.
Why is this happening and why is it only happening sometimes?
Code
I'm printing the list to the terminal in the following loop:
go func() {
defer donePrinting() // Tell the Stop function that we're done printing
ts := l.getTaskStates()
l.print(ts)
for {
select {
case <-ctx.Done(): // Check if the print loop should stop
// Perform a final clear and an optional print depending on `ClearOnComplete`
ts := l.getTaskStates()
if l.ClearOnComplete {
l.clear(ts)
return
}
l.clearThenPrint(ts)
return
case s := <-l.printQ: // Check if there's a message to print
fmt.Fprintln(l.Writer, s)
default: // Otherwise, print the list
ts := l.getTaskStates()
l.clearThenPrint(ts)
l.StatusIndicator.Next()
time.Sleep(l.Delay)
}
}
}()
The list is formatted as a string and then printed. The following function formats the string:
// fmtPrint returns the formatted list of messages
// and statuses, using the supplied TaskStates
func (l *List) fmtPrint(ts []*TaskState) string {
s := make([]string, 0)
for _, t := range ts {
s = append(s, l.formatMessage(t))
}
return strings.Join(s, "\n")
}
and the following function builds the ANSI escape string to clear the lines:
// fmtClear returns a string of ANSI escape characters
// to clear the `n` lines previously printed.
func (l *List) fmtClear(n int) string {
s := "\033[1A" // Move up a line
s += "\033[K" // Clear the line
s += "\r" // Move back to the beginning of the line
return strings.Repeat(s, n)
}
I'm using this site as a reference for the ANSI codes.
Thanks in advance for any suggestions you might have about why this is happening!
Let me know if there's any other information I can add that can help.
I think the ANSI codes are just a red herring. I pulled down the library and tried running it locally, and found that the following section is what is creating this issue:
case s := <-l.printQ: // Check if there's a message to print
fmt.Fprintln(l.Writer, s)
When the printQ channel is getting closed, this case is sometimes running, which seems to be moving the cursor down even though nothing is getting printed. This behaviour went away when I moved the call to close the channel after l.printDone is called.
...
// Wait for the print loop to finish
<-l.printDone
if l.printQ != nil {
close(l.printQ)
}
...
This ensures that the loop is no longer running when the channel is closed, and thus the s := <-l.printQ case cannot run.

golang erase symbols from console

I want to create animation in console, when program waits. There are a lot of simple ways to do this, usually, we just draw symbols in iterations of some cycle.
Let our code be:
func Spinner(delay time.Duration) {
for !StopSpinner{
for _, r := range `-\|/` {
fmt.Printf("\r%c", r)
time.Sleep(delay)
}
}
}
The problem is - how to remove animation, when there is no need in it from the console screen.
I tried escape sequences like fmt.Print("\b") or fmt.Printf("\r%s", "") but no result. I can not remove last symbol from screen and it concatenates with next text. How do you erase characters already printed to the console?
All you need to do is print a space (0x20) when you are done and that will overwrite the spinner.
ie: fmt.Fprint(os.Stdout, "\r \r") to put the cursor back to beginning of line after the space.
All you need to do is print a space (0x20) when you are done and that
will overwrite the spinner.
ie: fmt.Fprint("\r \r") to put the cursor back to beginning of line
after the space.
This answer is helpful, thank you!
But, there is an important detail!
Because the spinner function has a delay, it cannot stop exactly when StopSpinner boolean flag is set to true. So, I have added a channel for synchronization.
func Spinner(delay time.Duration) {
for !StopSpinner {
for _, r := range `-\|/` {
fmt.Printf("\r%c", r)
time.Sleep(delay)
}
}
fmt.Fprint("\r \r")
c <- struct{}{}
}
Now, calling function waits, while my spinner stop.
var c chan struct{} = make(chan struct{}) // event marker
func callingFunc(){
StopSpinner = false
go Spinner(100 * time.Millisecond)
// do something...
StopSpinner = true
<-c // wait spinner stop
//do something else
}
In my opinion, this is the complete solution!
fmt.Print("\033[H\033[2J")
This will put the cursor in the top left then clear the console as per this document of useful terminal commands:
https://www.student.cs.uwaterloo.ca/~cs452/terminal.html

unexpected case, expecting expression error when compiling go

When I compile the following code, it generates
*syntax error: unexpected case, expecting expression* at line *case workerAddr = <- mr.registerChannel:*
I do not know why it happens since I just want to workerAddr to be set by either channel. Any suggestion will be appreciated.
for i:= 0; i < mr.nMap; i++ {
go func(jobCount) {
for {
var workerAddr string
Select {
// get a worker either from registerChannel or from idle channel
case workerAddr = <- mr.registerChannel:
case workerAddr = <- mr.idleChannel:
}
// omit the following code
}
}(i)
}
It happens because you have written Select when you should have written select.
None of the Go keywords are capitalized, so when the compiler sees a capitalized word, it knows immediately that it's not an expression, and therefore a syntax error.

Let two renderui numeric inputs react on eachother in shiny

I'm trying to create two renderUI filters that have a value dependent on each other. I have two filters: percentage and value.
Percentage should be: value/total_amount and value should be total_amount*percentage. I need this because sometimes the user wants to fill in a number it wants and sometimes it wants a percentage of the total. And I always want to show both.
For example, if the user fills in .20 in the percentage filter, I want to show 20 in the value filter. And if the user fills in 80 in the value filter, I want to show .8 in the percentage filter.
So I'm hoping these two can be combined.. I'm trying this code but it's obviously not working.
server <- function(input, output) {
total_amount<-100
output$percentage<-renderUI({
myvalue<- input$value/total_amount
if(is.null(myvalue))myvalue<-.2
# myvalue<-.2
#browser()
numericInput('percentage','percentage',value = myvalue)
})
output$value<-renderUI({
myvalue<- input$percentage*total_amount
if(is.null(myvalue))myvalue<-100
# myvalue<-100
numericInput('value','value',value = myvalue)
})
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput('percentage'),
uiOutput('value')
)
# ,mainPanel(plotOutput("distPlot"))
)
)
shinyApp(ui = ui, server = server)
Just add the default value for the percentage and make sure that widget has a value.
library(shiny)
server <- function(input, output) {
total_amount <- 100
percentage <- 0.2
output$percentage <- renderUI({
if(is.null(input$value)) {
myvalue <- percentage
} else {
myvalue <- input$value/total_amount
}
numericInput('percentage', 'percentage', value = myvalue)
})
output$value <- renderUI({
if(is.null(input$percentage)) {
myvalue <- percentage*total_amount
} else {
myvalue <- input$percentage*total_amount
}
numericInput('value', 'value', value = myvalue)
})
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput('percentage'),
uiOutput('value')
)
,mainPanel()
)
)
shinyApp(ui = ui, server = server)

Resources