Reading vars from file, with spaces

Never had a need to, but now that I need to read text with spaces from files to put their contents into variables, I can’t seem to do so:

Piperead 'echo SetEnv explorer \
	$(cat $[FVWM_USERDIR]/sidepanel_info/explorer || \
	basename $( \
		which dolphin || \
		which konqueror || \
		which nautilus || \
		which thunar || \
		which rox || \
		which emelfm || \
		which emelfm2 || \
		which endeavour || \
		which krusader \
	))'

That should first check the file “explorer”, and put its contents into a var with the same name. But…

$ cat sidepanel_info/explorer 
konqueror --profile filemanagement ~ &> /dev/null
$ echo $explorer
konqueror

Is it that fvwm is just not capable of doing this? Any workaround?

Thanks in advance.

Double quotes,

Piperead 'echo SetEnv explorer \
	\\"$(cat $[FVWM_USERDIR]/sidepanel_info/explorer || \
	basename $( \
		which dolphin || \
		which konqueror || \
		which nautilus || \
		which thunar || \
		which rox || \
		which emelfm || \
		which emelfm2 || \
		which endeavour || \
		which krusader \
	))\\"'

Odd and nasty way of doing that. For a start I would stream-line it a bit:

PipeRead `echo SetEnv foo "$(<./file)" || ... || ...`

But then there’s no accounting for echoing out a script that FVWM could then interpret via “Read” instead.

– Thomas Adam

@zolar czakl

Thanks, that solved it, of course :slight_smile:

@Thomas, I know that it is a “bit” of overhead hehe, that was just meant to check something. I re-factored that the fvwm way, I think that this is a better approach, if you have a couple of seconds to spare let me know what do you think:

Test (r "$[FVWM_USERDIR]/sidepanel_info/p2p") \
	Piperead `echo SetEnv p2p \\"$(< $[FVWM_USERDIR]/sidepanel_info/p2p)\\"`
Test (!EnvIsSet p2p) Test (r "$[HOME]/.wine/drive_c/Program Files/eMule/emule.exe") \
	SetEnv p2p `cd \"$[HOME]/.wine/drive_c/Program Files/eMule/\" && wine emule.exe`
Test (!EnvIsSet p2p) Test (r "$[HOME]/.wine/drive_c/Archivos de programa/eMule/emule.exe") \
	SetEnv p2p `cd \"$[HOME]/.wine/drive_c/Program Files/eMule/\" && wine emule.exe`
Test (!EnvIsSet p2p) Test (x ktorrent) SetEnv p2p ktorrent
Test (!EnvIsSet p2p) Test (x kmldonkey) SetEnv p2p kmldonkey

I have not tested this thoroughly but I think that it should achieve the same effect. If that is not correct or there is a better way to do the same thing just point me in the right direction and I will dig a bit more. I am not too experienced with the fvwm Test conditions.

Thanks both :slight_smile:

I think I am more interested in what it is you’re trying to do. Read whichever sticky thread it is under “General FVWM Discussion” which explains why copious use of SetEnv will drag you to an early grave and ultimately raise my blood pressure beyond belief.

In the above you can rewrite it as:

Test (!EnvIsSet p2p, x ktorrent) SetEnv p2p ktorrent

Assuming the above is all in a function adding:

+ I TestRc (Match) Break

After each Test line will ensure you stop bothering to look when the first condition is matched. Again though, there’s hardly ever a need to go polluting the environment in this way.

So I’ll ask again: Just what is it you’re doing?

– Thomas Adam

Well, I am building some kind of configurable sidebar using FvwmButtons. It is a “bit” :smiling_imp: heavy, I am well aware of that.

The idea is the following:

First, I have redefined all the submenús this way (I’ll just use a random submenu as example, same for the rest):

DestroyMenu menu_Terms
Test (EnvMatch menu_edit_mode 0) AddToMenu menu_Terms "Terminal" Title
Test (EnvMatch menu_edit_mode 1) AddToMenu menu_Terms "Anclar al panel" Title
Test (x urxvt) + "&urxvt%terminal.svg:$[icon_size]%" parse_menu "terminal" "urxvt"
Test (x rxvt) + "&rxvt%terminal.svg:$[icon_size]%" parse_menu "terminal" "rxvt"
Test (x mrxvt) + "&mrxvt%terminal.svg:$[icon_size]%" parse_menu "terminal" "mrxvt"
Test (x aterm) + "&aterm%terminal.svg:$[icon_size]%" parse_menu "terminal" "aterm"
Test (x xterm) + "&xtern%terminal.svg:$[icon_size]%" parse_menu "terminal" "xterm"
Test (x eterm) + "&eterm%terminal.svg:$[icon_size]%" parse_menu "terminal" "eterm"

At the top of the config, the variable menu_edit_mode is initialized to “0”. Those functions are the grain of salt here :stuck_out_tongue:

DestroyFunc MenuEditMode_wrapper
AddToFunc MenuEditMode_wrapper
+ I SetEnv menu_edit_mode 1
+ I Read $[FVWM_USERDIR]/menu.config
+ I Menu "$0" Mouse +40 +0m
+ I SetEnv menu_edit_mode 0
+ I Read $[FVWM_USERDIR]/menu.config

DestroyFunc parse_menu
AddToFunc parse_menu
+ I Test (EnvMatch menu_edit_mode 1) change_button "$0" "$1"
+ I Test (EnvMatch menu_edit_mode 0) Exec exec bash -c "$1"

DestroyFunc change_button
AddToFunc change_button
+ I Piperead 'rm -f $[FVWM_USERDIR]/sidepanel_info/"$0"'
+ I Piperead 'echo "$1" > $[FVWM_USERDIR]/sidepanel_info/"$0"'
+ I SetEnv media "$1"
+ I Read $[FVWM_USERDIR]/side_menu.config

parse_menu is basically a wrapper, that acts depending upon the value of menu_edit_mode. I know that those are not optimal.

MenuEditMode_wrapper reads the menu.config file two times, in that file live all the menus, and that is needed to set the title of the menu depending on wether we are in edit mode or not, so the user can know if the next click is going to launch a menu or to put that application into the button that we are editing. The first argument in the menu definition -“terminal” in this case- is the name of the variable that we are modifying, that holds the command of the button that we are editing. The rest of the stuff is to save the thing into a file and then read it, so the settings are saved between sessions.

In FvwmButtons the thing works thigs way:

*FvwmSidebar: (1x1, Font $[ThemeHeadFont], Padding $[small_margin] 0, Title (Left) Terminal, \
    Action (Mouse 1) `Menu menu_Terms Mouse +40 +0m`, \
    Action (Mouse 2) `FvwmConsole -terminal $[terminal]`, \
    Action (Mouse 3) `MenuEditMode_wrapper "menu_Terms"`)
*FvwmSidebar: (1x1, Icon terminal.svg]*0.5+0-6, ActiveIcon terminal.svg]*0.6+0-6, PressIcon terminal.svg]*0.6+2-4, \
    Title (side) "$[terminal_title]", \
    Action (Mouse 1) `Exec exec $[terminal]`, \
    Action (Mouse 3) `MenuEditMode_wrapper "menu_Terms"`)

Which, basically outputs this

If you left click into the “Terminal” title, you get a menu with the available terms, a normal menu which will launch the clicked program.

If you right click it, you edit the entry below. The panel reloads and the default terminal program changes. If you left click the icon, the terminal is launched directly. A right click on the icon produces the same effect than a right click on the Terminal word.

The stuff in the posts above is the way to initialize the variable if no file is found (which basically means that the user did not configure the panel him/herself). It is a list of programs that the panel will search for if the user did not configure the panel.

In case you are curious about the crappy mess I organized, the whole config at its current state is here:
jesgue.homelinux.org/public/6thp … wm.tar.bz2

I considered packing this all under a function as you say, because of the Break statement, which is too convenient in this case. This is a task for another day and should not be a hard thing to do. I will also abreviatte the test statements as you suggested.

Thanks for taking the time to answer. The help is much appreciated.

PS- In case you want to dive into my config, the files related to this thing are menu.config, side_menu.config and functions.config. The menu_edit_mode var is into config. I have already implemented all the changes you suggested. Still to test them, but the functionality of the menu is intact after the changes. So, it is the blanked out setup which I need to test to see if the apps are found ok with all those Test clauses.

I had a very very very quick look, realised it was a mess with a number of glaring improvements that can be done.

I’ll pick this up again next week maybe, when I’m bored.

– Thomas Adam

Hello,

For now it kind of works. I made some improvements based on your suggestions. But I know that some parts are very far of being what I call a clean solution.

I continue polishing things a bit here and there, that link I posted above is a symlink and it always points to my latest config, so if you decide to investigate a bit on the thing, please, download it again when you are going to look into it, since now this config changes very quickly.

Again, thanks so much for taking the time to answer.

:slight_smile:

@Thomas, sorry to post again, but if you looked at my config yesterday, you might have seen something like:

DestroyFunc set_terminal
AddToFunc set_terminal
+ I Test (r $[FVWM_USERDIR]/sidepanel_info/terminal) \
	Piperead `echo SetEnv terminal \\"$(< $[FVWM_USERDIR]/sidepanel_info/terminal)\\"`
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x urxvt) SetEnv urxvt
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x rxvt) SetEnv rxvt
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x mrxvt) SetEnv mrxvtv
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x eterm) SetEnv eterm
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x aterm) SetEnv aterm
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x xtern) SetEnv xterm
+ I TestRc (Match) Break
set_terminal
SetEnv terminal_title $[terminal]

Which is not what it was meant to be. I changed this code -which is just used to initialize the variables for each sidebar button and since the config files were created it just looked the first line and worked. Of course the initialization if the “terminal” file is not present did not succeed, but as I did not test this yesterday, the error slipped (and I went to sleep :stuck_out_tongue: ).

The correct thing is this:

DestroyFunc set_terminal
AddToFunc set_terminal
+ I Test (r $[FVWM_USERDIR]/sidepanel_info/terminal) \
	Piperead `echo SetEnv terminal \\"$(< $[FVWM_USERDIR]/sidepanel_info/terminal)\\"`
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x urxvt) SetEnv terminal urxvt
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x rxvt) SetEnv terminal rxvt
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x mrxvt) SetEnv terminal mrxvtv
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x eterm) SetEnv terminal eterm
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x aterm) SetEnv terminal aterm
+ I TestRc (Match) Break
+ I Test (!EnvIsSet terminal, x xtern) SetEnv terminal xterm
+ I TestRc (Match) Break
set_terminal
SetEnv terminal_title $[terminal]

Which works as expected. Config updated, same link:
jesgue.homelinux.org/public/6thp … wm.tar.bz2

Removing the !EnvIsSet condition in the above clauses should work equally well. Shouldn’t it? Since if the previous Match is not true we can assume that we need to set this variable.

Regards.

That depends what you’re trying to achieve. Assuming the list of envvars is listed in order of precedence of matching then yes. If not, then leave it as it is.

– Thomas Adam