Havin_it Posted May 10, 2005 Report Share Posted May 10, 2005 'ning, So I had some problems with my touchpad driver, and at present my fix is to manually fix some of the settings using the synclient program (shared-memory config client for the Synaptics touchpad driver for X). For background, look here: https://mandrivausers.org/index.php?showtop...39entry184939 I need to issue a series of commands of the syntax synclient <Option>=<value> Rather than rewriting the values in the script every time I tinker with xorg.conf, I'd like it to actually read the values from xorg.conf and use them for the commands needed at runtime. I'm not even quite sure what tools/commands are best to do this. I know there are some string-filtering functions built into the shell, but are they sufficient? I once tried to use sed on Windows, and didn't even get my head round the manual. Here, I guess, is what the script must do: 1 - run the command: synclient -l (to get the actual runtime values) into a pipe or temp file 2 - Read the option-name and value from each line generated by (1), possibly into an associative array or a pair of numeric arrays 3 - For each option, find the corresponding line in xorg.conf (if the line exists - some will not) and read the value 4 - If the values do not match, issue: synclient <option-name>=<value-from-xorg.conf> It sounds simple to my mind, but I don't know how to go about the string-parsing part in this environment. Can anyone help? Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted May 10, 2005 Report Share Posted May 10, 2005 I assume synclient -l gives output lines looking like "option=value" (without quote). sed -n '/^[[:blank:]]*Identifier[[:blank:]]*"SynapticsMouse1"[[:blank:]]*$/,/^[[:blank:]]*EndSection [[:blank:]]*$/s/^[[:blank:]]*Option[[:blank:]]*"\([^="]*\)"[[:blank:]]*"\([^"]*\)"[[:blank:]] *$/=\1=\2/p' | grep -Ff <(synclient -l | sed -n 's/^\([^=]*\)=.*$/=\1=/p') | sed 's/^=//' | grep -vFxf <(synclient -l) | while read cmd; do eval synclient "'${cmd}'"; done This is a rough try. A better solution might be needed if synclient -l is long to execute (as it is executed twice here), and besides, there's no way I can test any of this. Yves. Quote Link to comment Share on other sites More sharing options...
Havin_it Posted May 10, 2005 Author Report Share Posted May 10, 2005 Hi Yves, thanks for the quick reply! Blimey, is that all one line? no wonder I got scared off with sed earlier... The synclient command is really quick in the terminal, so no problem there. And you're correct about the output format, apart from some spaces and tabs and the first line. The second code box in the linked post above is the exact output. so how do I specify /etc/X11/XF86Config as the file to be read from? Quote Link to comment Share on other sites More sharing options...
Havin_it Posted May 10, 2005 Author Report Share Posted May 10, 2005 Okay, I bit the bullet and tried reading up a little on sed (not from the manpage, it's hopeless, but from some of the linked docs on the homepage). Still haven't understood much, but this does the trick for outputting a 'clean' list of option-value pairs from synclient: synclient -l | grep = | sed 's/[ ]//g' Guess doing the same for XF86Config is a fair bit harder, which is what the above is for? Will keep playing and see what I learn. Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted May 11, 2005 Report Share Posted May 11, 2005 (edited) Blimey, is that all one line? no wonder I got scared off with sed earlier...The synclient command is really quick in the terminal, so no problem there. And you're correct about the output format, apart from some spaces and tabs and the first line. The second code box in the linked post above is the exact output. so how do I specify /etc/X11/XF86Config as the file to be read from? <{POST_SNAPBACK}> I'll try and explain. I wrote that in a bit of a hurry, and indeed, I forgot to write the name of the file to read from :lol: sed -n '/^[[:blank:]]*Driver[[:blank:]]*"synaptics"[[:blank:]]*$/,/^[[:blank:]]*EndSection[[:blank:]]*$/ tells sed to not output anything by default (-n), and look for the part of the text that starts with 'Driver "synaptics"' (small change here, more reliable I think), and ends with 'EndSection'. The '[[:blank:]]*' everywhere are there to be "blank-proof", in case you use tabs or spaces. Now if this block is found, for each line inside sed executes: s/^[[:blank:]]*Option[[:blank:]]*"\([^="]*\)"[[:blank:]]*"\([^"]*\)"[[:blank:]]*$/=\1=\2/p' /etc/X11/XF86Config (file added :) ) a line is printed only if it matches '"Option" = "Value"', with all spaces removed, and with an '=' added as first character (this is because next grep will work without regular expressions, and we want to find the start of line). Then grep filters the result so: grep -Ff <(synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=.*$/=\1=/p') which means that only lines that start with an option known to synclient are kept. The notation '<()' is a bash notation to view a subprocess' output as if it were a file. Now we don't need the initial '=' so it is easily removed. Finally, grep filters the result by removing all options that are already set (as reported by synclient): grep -vFxf <(synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=[[:blank:]]*\([^[:blank:]]*\)[[:blank:]]*$/\1=\2/p') Option -v is to exclude, -F is to search text instead of regexps, -x is to have only full lines, and -f is to select the file where forbiden lines are stored, and is the result of reformating synclient output (blanks now taken into account). Which just leaves to execute each remaining command: while read cmd; do eval synclient "'${cmd}'"; done The full line can be written in your startup script, and broken into lines for better readability: ... whatever is already there in the file ... [1]sed -n ' [2] /^[[:blank:]]*Driver[[:blank:]]*"synaptics"[[:blank:]]*$/,/^[[:blank:]]*EndSection[[:blank:]]*$/ { [3] s/^[[:blank:]]*Option[[:blank:]]*"\([^="]*\)"[[:blank:]]*"\([^"]*\)"[[:blank:]]*$/=\1=\2/p [4] } [5]' /etc/X11/XF86Config \ [6]| grep -Ff <(synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=.*$/=\1=/p') \ [7]| sed 's/^=//' \ [8]| grep -vFxf <(synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=[[:blank:]]*\([^[:blank:]]*\)[[:blank:]]*$/\1=\2/p') \ [9]| while read cmd; do eval synclient "'${cmd}'"; done [edit:]I added line numbers above between brackets, so that you know where each line starts.[/edit] I still can't test, though... Yves. Edited May 11, 2005 by theYinYeti Quote Link to comment Share on other sites More sharing options...
Havin_it Posted May 11, 2005 Author Report Share Posted May 11, 2005 Thanks for the detailed explanation, Yves. I do want to learn how to use these commands myself, not just grab a script off the shelf, so I appreciate you breaking it down for me so I can see what's what. I'm going to see if I can add what I learned overnight to what you have given me, because I just realised it might be wise for me to only read a smaller chunk of the XF86Config (from below the 'SHMConfig' line). I think I can do that now, but I'll post back what I come up with and if it works. Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted May 11, 2005 Report Share Posted May 11, 2005 Thanks for the detailed explanation, Yves. I do want to learn how to use these commands myself, not just grab a script off the shelf, so I appreciate you breaking it down for me so I can see what's what. You're welcome! I can understand that. Myself, I'd never even think of using a script without understanding it, and often tweak it, because a script is an over-powerfull tool, that can do much damage if not used as it was intended to be. Yves. Quote Link to comment Share on other sites More sharing options...
Havin_it Posted May 11, 2005 Author Report Share Posted May 11, 2005 Not done yet by any means, but with the advantage of knowing some particulars of the file and the strings needed, I was able to come up with this, which takes us up to line [5] in your script. grep '^ Option' /etc/X11/xorg.conf | egrep -v Device\|Protocol\|SHMConfig | sed 's/[ ]\+Option[\t]\+"\([A-Za-z]\+\)"[\t]\+"\([0-9\.]\+\)"/=\1=\2/' # one line, I'm just shooting off commands in console so far... The Option lines I need to read were copied out of the driver's README file so their line-start spacing is unique in the file (handy!) - so as long as any additions I make also start with two spaces and use tabs inbetween, it remains effective. After that point - and I'll stress that I'm still not aware enough to be certain - I think you diverged from the spec. The thing is, the offending values that need to be corrected, _are_ already defined in the output, but defined wrong. So the next job, in effect, is to identify options that are in the synclient output, but whose values don't match the ones we've retrieved from the file. I'm sorry if I misunderstand what the final parts of the code is doing, I'm not certain at all, and I'm grateful for your help. We can use grep and sed again to construct a stream with the same format as the one we've produced from the file, so the last parts should be, 1) For each line in the XF86Config stream, search for the matching option in the synclient stream. If [a] it's there and the value is different, output it. 2) Take the output from (1) and execute 'synclient <line>' for each line. Quote Link to comment Share on other sites More sharing options...
Havin_it Posted May 11, 2005 Author Report Share Posted May 11, 2005 **POSSIBLE COP-OUT APPROACHING** Something occurred to me about the last part of the task. What I proposed in the last post is gonna require a few more pipes, a fair bit of looping, and goodness knows what else. Soooo... What if I just have synclient run _all_ the configs generated by the earlier steps? I'd still know if any newly-added configs were malformed because synclient would puke, and the commands run really quick so I know it's not taxing the system too much. Seems like a better option in practical terms, though it'd still be interesting to bear out the original method to see how it could be done. I'd still like to see some kind of output on the operation, to show what was changed. Maybe if I store the original synclient output before starting, then repeat afterwards, and do some type of 'diff' on the two outputs. Just thinking aloud really - what do you think, Yves? Would completing the script in the originally intended manner be a major resource-eater? Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted May 11, 2005 Report Share Posted May 11, 2005 I have to go, but I'll have a look at it tomorow. Bye, Yves. Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted May 12, 2005 Report Share Posted May 12, 2005 1) For each line in the XF86Config stream, search for the matching option in the synclient stream. If [a] it's there and the value is different, output it.2) Take the output from (1) and execute 'synclient <line>' for each line. Unless there's something I don't understand, that's exactly what lines [6] to [9] do... I'll try and explain a bit more, based on the formerly linked-to post you wrote. synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=.*$/=\1=/p' should give: =LeftEdge= =RightEdge= =TopEdge= =BottomEdge= =FingerLow= =FingerHigh= =MaxTapTime= ...and so on. synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=[[:blank:]]*\([^[:blank:]]*\)[[:blank:]]*$/\1=\2/p' should give: LeftEdge=120 RightEdge=830 TopEdge=120 BottomEdge=650 FingerLow=14 FingerHigh=15 MaxTapTime=0 ...and so on. Now under each step, I'll write what I expect to be the result: [1]sed -n ' [2] /^[[:blank:]]*Driver[[:blank:]]*"synaptics"[[:blank:]]*$/,/^[[:blank:]]*EndSection[[:blank:]]*$/ { [3] s/^[[:blank:]]*Option[[:blank:]]*"\([^="]*\)"[[:blank:]]*"\([^"]*\)"[[:blank:]]*$/=\1=\2/p [4] } [5]' /etc/X11/XF86Config \ =Device=/dev/psaux =Protocol=auto-dev =SHMConfig=1 =LeftEdge=120 =RightEdge=830 =TopEdge=120 =BottomEdge=650 =FingerLow=14 =FingerHigh=15 =MaxTapTime=150 =MaxTapMove=110 =MaxDoubleTapTime=400 =ClickTime=30 =EmulateMidButtonTime=75 =VertScrollDelta=20 =HorizScrollDelta=20 =MinSpeed=0.3 =MaxSpeed=0.75 =AccelFactor=0.015 =EdgeMotionMinSpeed=2 =EdgeMotionMaxSpeed=4 =UpDownScrolling=1 [6]| grep -Ff <(synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=.*$/=\1=/p') \ =LeftEdge=120 =RightEdge=830 =TopEdge=120 =BottomEdge=650 =FingerLow=14 =FingerHigh=15 =MaxTapTime=150 =MaxTapMove=110 =MaxDoubleTapTime=400 =ClickTime=30 =EmulateMidButtonTime=75 =VertScrollDelta=20 =HorizScrollDelta=20 =MinSpeed=0.3 =MaxSpeed=0.75 =AccelFactor=0.015 =EdgeMotionMinSpeed=2 =EdgeMotionMaxSpeed=4 =UpDownScrolling=1 [7]| sed 's/^=//' \ LeftEdge=120 RightEdge=830 TopEdge=120 BottomEdge=650 FingerLow=14 FingerHigh=15 MaxTapTime=150 MaxTapMove=110 MaxDoubleTapTime=400 ClickTime=30 EmulateMidButtonTime=75 VertScrollDelta=20 HorizScrollDelta=20 MinSpeed=0.3 MaxSpeed=0.75 AccelFactor=0.015 EdgeMotionMinSpeed=2 EdgeMotionMaxSpeed=4 UpDownScrolling=1 [8]| grep -vFxf <(synclient -l | sed -n 's/^[[:blank:]]*\([^[:blank:]=]*\)[[:blank:]]*=[[:blank:]]*\([^[:blank:]]*\)[[:blank:]]*$/\1=\2/p') \ MaxTapTime=150 MaxDoubleTapTime=400 ClickTime=30 HorizScrollDelta=20 EdgeMotionMinSpeed=2 EdgeMotionMaxSpeed=4 [9]| while read cmd; do eval synclient "'${cmd}'"; done execute: synclient 'MaxTapTime=150' synclient 'MaxDoubleTapTime=400' synclient 'ClickTime=30' synclient 'HorizScrollDelta=20' synclient 'EdgeMotionMinSpeed=2' synclient 'EdgeMotionMaxSpeed=4' Is that what you expect? Maybe there's something I did not understand correctly... Yves. Quote Link to comment Share on other sites More sharing options...
Havin_it Posted May 12, 2005 Author Report Share Posted May 12, 2005 I really should have studied your script more carefully! My misapprehension came from the wording of your explanation, more than the code (which I hadn't understood yet). Thanks for bearing with a fool! I'll run it and see how it goes, like I should have in the first place! Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted May 12, 2005 Report Share Posted May 12, 2005 ... You make me feel embarassed :lol: ... Never trust anyone's code (not even mine) until you at least understand the general working of it. That's not because we're bad people :) but because we can all make mistakes (especially when no test is possible), and a little misunderstanding may lead to a script that does something absolutely different from what you intended, and possibly devastating... It's nice that you learn and understand what others suggest :) Yves. Quote Link to comment Share on other sites More sharing options...
Havin_it Posted May 12, 2005 Author Report Share Posted May 12, 2005 Cool, I - sorry, we - have finally done it! #!/bin/bash echo Correcting all synaptics settings... grep '^ Option' /etc/X11/xorg.conf | egrep -v Device\|Protocol\|SHMConfig | sed 's/[ ]\+Option[\t]\+"\([A-Za-z]\+\)"[\t]\+"\([0-9\.]\+\)"/\1=\2/' | grep -vFxf <(synclient -l | sed -n 's/^[ ]\+\([A-Za-z]\+\)[ ]\+=[ ]\+\([0-9\.]\+\)[ ]*$/\1=\2/p') | while read cmd; do (eval synclient "${cmd}" || echo Couldn\'t add value "${cmd}") && echo Bullied value "${cmd}"; done echo Done. Yves, this is I think essentially what you provided to begin with, just boiled down a little (alphanumerics for the options, floats for the values, and spaces/tabs for blanks because I have the luxury of knowing which goes where :) ) and with a bit of error-trapping added. I wondered for a long time why it puked with syntax-errors when I ran it in console, it has something to do with Bash bersus sh it seems, so I made it explicitly a Bash script (funny, I always thought it was the same thing on Mandrake!) Anyway, this baby is going in my KDE Autostart folder - I guess it could go somewhere in the init system after X starting, but this is just easier for me since I only use KDE. Every time I posted in this thread I thanked Yves, and this is no exception dammit! I think this is the most important forum on this board for committed Linux learners, and sir you do it proud. Thank you! Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted May 13, 2005 Report Share Posted May 13, 2005 :blush: :) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.