Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify monospace font in `menu`

Language: R. Question: Can I specify fixed width font for the menu(..,graphics=T) function?

Explanation:

I recently asked this question on how to have a user select a row of a data frame interactively:

df <- data.frame(a=c(9,10),b=c('hello','bananas')) df.text <- apply( df, 1, paste, collapse=" | " ) menu(df.text,graphics=T) 

enter image description here

I'd like the | to line up. They don't at the moment; fair enough, I haven't padded out the columns to the same width. So I use format to get every column to the same width (later I'll write code to automagically determine the width per column, but let's ignore that for now):

df.padded <- apply(df,2,format,width=8) df.padded.text <- apply( df.padded, 1, paste, collapse=" | ") menu( df.padded.text,graphics=T ) 

enter image description here

See how it's still wonky? Yet, if I look at df.padded, I get:

> df.padded      a            b            [1,] " 9        " "hello     " [2,] "10        " "bananas   " 

So each cell is definitely padded out to the same length.

The reason for this is probably because the default font for this (on my system anyway, Linux) is not fixed width.

So my question is: Can I specify fixed width font for the menu(..,graphics=T) function?

Update

@RichieCotton noticed that if you look at menu with graphics=T it calls select.list, which in turn calls tcltk::tk_select.list.

So it looks like I'll have to modify tcltk options for this. From @jverzani:

library(tcltk) tcl("option", "add", "*Listbox.font", "courier 10") menu(df.padded.text,graphics=T) 

enter image description here

Given that menu(...,graphics=T) calls tcltk::tk_select.list when graphics is TRUE, my guess is that this is a viable option, as any distro that would be capable of displaying the graphical menu in the first place would also have tcltk on it, since it needs to call tk_select.list.

(As an aside, I can't find anything in the documentation that would give me the hint to try tcl('option','add',...), let alone that the option was called *Listbox.font!)

Another update -- had a closer look at the select.list and menu code, and it turns out on Windows (or if .Platform$GUI=='AQUA' -- is that Mac?), the tcltk::tk_select.list isn't called at all, and it's just some internal code instead. So modifying '*Listbox.font' won't affect this.

I guess I'll just:

  • if tcltk is there, load it, set the *Listbox.font to courier, and use tcltk::tk_select.list explicitly
  • if it isn't there, try menu(...,graphics=T) to at least get a graphical interface (which won't be monospace, but is better than nothing)
  • if that fails too, then just fallback to menu(...,graphics=F), which will definitely work.

Thanks all.

like image 763
mathematical.coffee Avatar asked Feb 08 '12 07:02

mathematical.coffee


People also ask

How do I monospace a font?

Basically, for a font to be considered monospace, every glyph has to be the same width, right down to the exact same number of units. This includes even glyphs that should normally be zero width, or a certain width (such as em spaces, em dashes, etc).

What is the standard monospace font?

Courier is the traditional monospace font.

What is monospaced font in Word?

Monospaced fonts have constant spacing between characters while proportional fonts have variable spacing between characters.

Why do programmers use monospaced fonts?

Consequently, most coders prefer retro-style monospaced fonts, where each character takes up the exact same amount of horizontal space. Because a single typo can mess everything up, these simple, monospaced fonts make code a lot easier to read.


1 Answers

Another approach to padding:

na.pad <- function(x,len){     x[1:len] }  makePaddedDataFrame <- function(l,...){     maxlen <- max(sapply(l,length))     data.frame(lapply(l,na.pad,len=maxlen),...) }  x = c(rep("one",2)) y = c(rep("two",10)) z = c(rep("three",5))  makePaddedDataFrame(list(x=x,y=y,z=z)) 

The na.pad() function exploits the fact that R will automatically pad a vector with NAs if you try to index non-existent elements.

makePaddedDataFrame() just finds the longest one and pads the rest up to a matching length.

like image 110
reuf Avatar answered Oct 03 '22 09:10

reuf