You are not logged in.

#41 2015-10-16 04:21:35

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,668
Website

Re: Movable conkys

Sector11 wrote:

And [Alt]+Rclick to resize it too!

Didn't know that one!


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#42 2015-10-16 08:05:01

Snap
Member
Registered: 2015-10-02
Posts: 465

Re: Movable conkys

Those commands are cool if you are on metal, but for virtual machines the host steals all Alt clicks. This script would be a blessing. And sure many bare metal runners will love it too.

Offline

#43 2015-10-16 08:12:16

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,668
Website

Re: Movable conkys

Yes I ran into that Alt-stealing on VirtualBox.
But the idea of this script is to let people drag their conky where they want, and then run the utility to rewrite the config file with the new position.

There are other tools to actually move windows, though.
Maybe eg xdotool could be used to simulate an Alt-click-drag, and tied to another key combo? Or maybe another key could just be mapped to Alt? Might that work on a VM? Have no time to try right now...


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#44 2015-10-16 09:50:01

Snap
Member
Registered: 2015-10-02
Posts: 465

Re: Movable conkys

Yes, xdotool should do it and can be added to autostart or xinitrc to make it somewhat persistent. but it's a dirtier workaround since it won't touch the configs.

Offline

#45 2015-10-17 08:58:23

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,668
Website

Re: Movable conkys

A function to edit a conky file. Feed it the filepath, then the config values you want to change, like name=value (or name='two words'). It uses parseconkyfile() to read the file first. If some value hasn't been changed before it adds a comment '#conkymove, original name:'. If you try to change a value that doesn't exist it errors out. If the value you set is the same as what's there already it just passes on. Finally, sed writes in the changes.

# makes array "config"
parse_conkyfile()
{
    [[ -f $1 ]] || { echo "$1 is not a file." >&2;return 1;}
    unset config
    declare -Ag config
    local name value
    while read name value
    do
        [[ $name ]] || continue
        [[ $name = TEXT* ]] && break
        config["$name"]="$value"
    done < <(sed 's/\#.*$//' "$1")
}

# usage: edit_conkyfile file name=value [name2=value2...]
# use absolute path to file
edit_conkyfile() {
    [[ $1 = /* ]] || {
        echo "$0: $1 is not an absolute path." >&2
        return 1
    }
    file=$1
    shift
    parse_conkyfile "$file"
    local name value
    unset sed_cmd
    while [[ $1 ]]; do
        unset name value sed_pattern sed_replace
        name="${1%%=*}"
        value="${1#*=}"
        shift
        [[ ${config["$name"]+x} ]] || {
            echo "$0: config key $name does not exist" >&2
            return 1
        }
        [[ ${config["$name"]//[[:space:]]} = "${value//[[:space:]]}" ]] && continue
        sed_pattern="^ *$name .*$"
        grep -q "#conkymove, original $name:" "$file" || sed_replace="#conkymove, original $name: ${config[$name]}\n"
        sed_replace+="$name $value"
        sed_cmd+="s/$sed_pattern/$sed_replace/;"
    done
    [[ "$sed_cmd" ]] && {
        sed -ri "$sed_cmd" "$file"
    }
}

Last edited by johnraff (2015-10-17 08:59:16)


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#46 2015-11-07 16:22:25

damo
....moderator....
Registered: 2015-08-20
Posts: 6,734

Re: Movable conkys

OK, this is working, after a fashion - using @johnraff's functions to write the positions into the conkyrc seems to be a good solution.  By setting the alignment to "top left", the absolute `x` and `y` values can be used, and so getting the conky geometry isn't necessary.

The offsets need some more investigation, and I think that all pinned conkys may need to have all border values parsed. ATM there is a slight creep every time the pinning is repeated (in various directions, depending on the conky!), but if it is rarely done it is unlikely to be noticeable.

This WIP pins all running conkys, but it would be nice to be able to choose by clicking on one. This should be easy enough with a zenity dialog and using an `xdotool` command to get the selected window

#!/bin/bash
##

OFFSET_X=5
OFFSET_Y=5

# makes array "config"
parse_conkyfile()
{
    [[ -f $1 ]] || { echo "$1 is not a file." >&2;return 1;}
    unset config
    declare -Ag config
    local name value
    while read name value
    do
        [[ $name ]] || continue
        [[ $name = TEXT* ]] && break
        config["$name"]="$value"
    done < <(sed 's/\#.*$//' "$1")
}

# usage: edit_conkyfile file name=value [name2=value2...]
# use absolute path to file
edit_conkyfile() {
    [[ $1 = /* ]] || {
        echo "$0: $1 is not an absolute path." >&2
        return 1
    }
    file=$1
    shift
    parse_conkyfile "$file"
    local name value
    unset sed_cmd
    while [[ $1 ]]; do
        unset name value sed_pattern sed_replace
        name="${1%%=*}"
        value="${1#*=}"
        shift
        [[ ${config["$name"]+x} ]] || {
            echo "$0: config key $name does not exist" >&2
            return 1
        }
        [[ ${config["$name"]//[[:space:]]} = "${value//[[:space:]]}" ]] && continue
        sed_pattern="^ *$name .*$"
        grep -q "#conkymove, original $name:" "$file" || sed_replace="#conkymove, original $name: ${config[$name]}\n"
        sed_replace+="$name $value"
        sed_cmd+="s/$sed_pattern/$sed_replace/;"
    done
    [[ "$sed_cmd" ]] && {
        sed -ri "$sed_cmd" "$file"
    }
}

while read CONK;do
    ID=${CONK%% *}
    CMD=$(xprop -id $ID  WM_COMMAND | grep -o '".*"' | sed 's/["|,]//g')
    CONKYPATH=${CMD##* }

    WINX=$(xwininfo -int -id $ID  | grep "Absolute upper-left X")
    posX=${WINX##* }
    posX=$(( posX + OFFSET_X ))
    
    WINY=$(xwininfo -int -id $ID  | grep "Absolute upper-left Y")
    posY=${WINY##* }
    posY=$(( posY + OFFSET_Y ))

    edit_conkyfile "$CONKYPATH" "alignment"="tl" "gap_x"=$posX "gap_y"=$posY
    
done < <(xdotool search --class "Conky")

Be Excellent to Each Other...
The Bunsenlabs Lithium Desktop » Here
FORUM RULES and posting guidelines «» Help page for forum post formatting
Artwork on DeviantArt  «» BunsenLabs on DeviantArt

Offline

#47 2015-11-08 05:49:18

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,668
Website

Re: Movable conkys

Hi Damo, looks like we've both been tinkering with this...

Before I post my contribution, can I suggest a modification to

CMD=$(xprop -id $ID  WM_COMMAND | grep -o '".*"' | sed 's/["|,]//g')

to use this long long awk thing:

CMD=$(xprop -id $ID  WM_COMMAND | awk -F '", "' '{cmd=$1;sub(/^.*{ "/,"",cmd);for (i=1;i<=NF;i++)if($i=="-c"){i++;sub(/\" }$/,"",$i);gsub(/\\\"/,"\"",$i);print cmd,$i;exit}}')

I'm sorry it's so clunky-looking, but it is a bit more solid: it copes with filepaths containing " and it grabs the config path from whatever argument follows -c (I'll add --config= in the future) regardless of where it comes in the command line. It outputs 'conky /path/to/file' so the rest of your script should work as-is.

That's a good idea to search windows using the "class". I don't know much about that stuff, and used wmctrl -l and then just chose the titles with conky in. That pulls in Geany or Iceweasel if they're doing something with conky in, and I had to filter them out using the command 'conky' from $CMD. Your way using 'xdotool search --class' gets past that. The disadvantage of that approach is that you still need to go back to an x-tool, xwininfo, to get the position, while wmctrl -lG will give you all that in one go, plus width, height etc. I might try adding -x to wmctrl's options, that would allow that awful awk line to be a bit shorter too...

Anyway, I haven't yet got to editing the conky file, but I made this script to try and research the X and Y offsets - I think it's the same for both, called it $FUDGE_FACTOR and agree it seems to be 5px on Wheezy, but needed 7px for me on Jessie. If you run this script it will ask you for the fudge factor then run an algorithm to try and calculate the x and x position from what's in the conffile (taking account of alignment) and compare it with what wmctrl reports the actual position to be.

It's working (with fudge of 7 in BL) on most conkys in the default collection on the 3 computers I have (so seems to cope with different resolutions) but there is a glitch of 2px with the Classic.conkyrc for some reason. More research...

# makes array "config"
# usage: parse_conkyfile file
parse_conkyfile() {
    unset config
    [[ -r "$1" ]] || { echo "cannot read $1" >&2;return 1;}
    declare -Ag config
    local name value
    while read name value
    do
        [[ $name ]] || continue
        [[ $name = TEXT* ]] && break
        config["$name"]="$value"
    done < <(sed 's/\#.*$//' "$1")
}

# convert conky settings to x y xwindow position
# usage: conky2xy file
# array: 'win' and string: 'screen_dims' must be set
conky2xy() {
    [[ $1 = /* ]] || {
        echo "$0: $1 is not an absolute path." >&2
        return 1
    }
    parse_conkyfile "$1"
    case "${config[alignment]}" in
    top_left|tl)
        config[xoffset]=$((${config[gap_x]}-$fudge))
        config[yoffset]=$((${config[gap_y]}-$fudge))
    ;;
    top_right|tr)
        config[xoffset]=$((${screen_dims%x*}-${config[gap_x]}-${win[width]}+$fudge))
        config[yoffset]=$((${config[gap_y]}-$fudge))
    ;;
    top_middle|tm)
        config[xoffset]=$((${screen_dims%x*}/2-${win[width]}/2-${config[gap_x]}))
        config[yoffset]=$((${config[gap_y]}-$fudge))
    ;;
    bottom_left|bl)
        config[xoffset]=$((${config[gap_x]}-$fudge))
        config[yoffset]=$((${screen_dims#*x}-${config[gap_y]}-${win[height]}+$fudge))
    ;;
    bottom_right|br)
        config[xoffset]=$((${screen_dims%x*}-${config[gap_x]}-${win[width]}+$fudge))
        config[yoffset]=$((${screen_dims#*x}-${config[gap_y]}-${win[height]}+$fudge))
    ;;
    bottom_middle|bm)
        config[xoffset]=$((${screen_dims%x*}/2-${win[width]}/2-${config[gap_x]}))
        config[yoffset]=$((${screen_dims#*x}-${config[gap_y]}-${win[height]}+$fudge))
    ;;
    middle_left|ml)
        config[xoffset]=$((${config[gap_x]}-$fudge))
        config[yoffset]=$((${screen_dims#*x}/2-${win[height]}/2-${config[gap_y]}))
    ;;
    middle_right|mr)
        config[xoffset]=$((${screen_dims%x*}-${config[gap_x]}-${win[width]}+$fudge))
        config[yoffset]=$((${screen_dims#*x}/2-${win[height]}/2-${config[gap_y]}))
    ;;
    middle_middle|mm)
        config[xoffset]=$((${screen_dims%x*}/2-${win[width]}/2-${config[gap_x]}))
        config[yoffset]=$((${screen_dims#*x}/2-${win[height]}/2-${config[gap_y]}))
    ;;
    esac
}

check() {
    echo "Enter FUDGE FACTOR"
    read -r
    fudge=$REPLY
    echo "FUDGE FACTOR is set at ${fudge}px"
    screen_dims=$(xrandr --current | awk '/\*/{print $1}')
    echo "Screen dimensions: $screen_dims"$'\n'
    unset win
    declare -A win
    while read win[id] win[desktop] win[xoffset] win[yoffset] win[width] win[height] win[client] win[title]
    do
        unset cmd_file
        [[ ${win[title]} = *[Cc]onky* ]] || continue
        cmd_file=$(xprop -id ${win[id]}  WM_COMMAND | awk -F '", "' '{cmd=$1;sub(/^.*{ "/,"",cmd);for (i=1;i<=NF;i++)if($i=="-c"){i++;sub(/\" }$/,"",$i);gsub(/\\\"/,"\"",$i);print cmd,$i;exit}}')
        [[ ${cmd_file%% *} = conky ]] || continue
        cfgfile="${cmd_file#* }"
        conky2xy "$cfgfile"
        echo "ID: ${win[id]}
Title: ${win[title]}
File: $cfgfile
Calculated from config file, X: ${config[xoffset]}
Position from Wmctrl, X: ${win[xoffset]}
Calculated from config file, Y: ${config[yoffset]}
Position from Wmctrl, Y: ${win[yoffset]}
"
    done < <(wmctrl -lG)
}

check

If this could be got to report 100% accurately, then it would be possible to reverse the algorithm to edit the conffile I guess.


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#48 2015-11-08 09:37:49

damo
....moderator....
Registered: 2015-08-20
Posts: 6,734

Re: Movable conkys

The "fudge-factor" falls down due to `borders`, which may or may not be set, as I posted earlier. Some configs might be out by a looong way, and I found that repeating the pinning may move different conkys in different directions by a few px.

I have been trying your idea of getting the delta of the positions before and after, and using that as the offset for `gapx` and `gap_y`. I'm also on-track for selecting a single conky and pinning it individually.


Be Excellent to Each Other...
The Bunsenlabs Lithium Desktop » Here
FORUM RULES and posting guidelines «» Help page for forum post formatting
Artwork on DeviantArt  «» BunsenLabs on DeviantArt

Offline

#49 2015-11-08 15:06:04

damo
....moderator....
Registered: 2015-08-20
Posts: 6,734

Re: Movable conkys

Script to select a moveable Conky, and set its new position by writing `gap_x` and `gap_y` to the conkyrc.
If the conky has `alignment none`, placement can be left to Openbox, so the script exits with an appropriate message.

The new position is calculated using the difference from the original, so there is no need for a "fudge factor".

conkypin

#!/bin/bash
##
#   Script to set the position of a moveable Conky
#
#   Written by damo <damo@bunsenlabs.org> November 2015
#   with major contributions of functions, commands and suggestions by @johnraff

DIALOG="yad --center --undecorated --borders=20 \
--window-icon=/usr/share/pixmaps/Bunsenlabs-flame-256.svg"

unset CONKYPATH posX_1 posY_1 posX_2 posY_2 OFFSET_X OFFSET_Y gapX gapY

# makes array "config"
function parse_conkyfile(){   # function by @johnraff
    [[ -f $1 ]] || { echo "$1 is not a file." >&2;return 1;}
    unset config
    declare -Ag config
    local name value
    while read name value
    do
        [[ $name ]] || continue
        [[ $name = TEXT* ]] && break
        config["$name"]="$value"
    done < <(sed 's/\#.*$//' "$1")
}

# usage: edit_conkyfile file name=value [name2=value2...]
# use absolute path to file
function edit_conkyfile(){   # function by @johnraff
    [[ $1 = /* ]] || {
        echo "$0: $1 is not an absolute path." >&2
        return 1
    }
    file=$1
    shift
    parse_conkyfile "$file"
    local name value
    unset sed_cmd
    while [[ $1 ]]; do
        unset name value sed_pattern sed_replace
        name="${1%%=*}"
        value="${1#*=}"
        shift
        [[ ${config["$name"]+x} ]] || {
            echo "$0: config key $name does not exist" >&2
            return 1
        }
        [[ ${config["$name"]//[[:space:]]} = "${value//[[:space:]]}" ]] && continue
        sed_pattern="^ *$name .*$"
        grep -q "#conkymove, original $name:" "$file" || sed_replace="#conkymove, original $name: ${config[$name]}\n"
        sed_replace+="$name $value"
        sed_cmd+="s/$sed_pattern/$sed_replace/;"
    done
    [[ "$sed_cmd" ]] && {
        sed -ri "$sed_cmd" "$file"
    }
}

function getStart(){    #   Get initial Conky position
    unset CONKYPATH
    while read CLICKED;do
        ID=$(grep "Window id:" | awk '{print $4}') <<< $CLICKED
    done < <(xwininfo)
    
    # command suggested by @johnraff....
    CMD=$(xprop -id $ID  WM_COMMAND | awk -F '", "' '{cmd=$1;sub(/^.*{ "/,"",cmd);for (i=1;i<=NF;i++)if($i=="-c"){i++;sub(/\" }$/,"",$i);gsub(/\\\"/,"\"",$i);print cmd,$i;exit}}')

    if grep "conky" <<< $CMD &>/dev/null;then
        echo "Found a conky"
        CONKYPATH=${CMD##* }
        WINX_1=$(xwininfo -int -id $ID  | grep "Absolute upper-left X")
        posX_1=${WINX_1##* }
        WINY_1=$(xwininfo -int -id $ID  | grep "Absolute upper-left Y")
        posY_1=${WINY_1##* }
    else
        echo "Selection is not a conky"
        $DIALOG --button="OK:0" --text="Selection is not a conky\n\nChoose again"
        getStart
    fi
}

function getFinish(){   #   Get new Conky position
    WINX_2=$(xwininfo -int -id $ID  | grep "Absolute upper-left X")
    posX_2=${WINX_2##* }
    WINY_2=$(xwininfo -int -id $ID  | grep "Absolute upper-left Y")
    posY_2=${WINY_2##* }
}

function getOffset(){
    unset VAR VAL
    while read VAR VAL;do
        case $VAR in
            alignment)  align="$VAL";;
            gap_x    )  gapX=$VAL;;
            gap_y    )  gapY=$VAL;;
        esac
    done < <(cat $CONKYPATH)

    OFFSET_X=$(( posX_2 - posX_1 ))
    OFFSET_Y=$(( posY_2 - posY_1 ))

    case $align in 
        tr|top_right|mr|middle_right|br|bottom_right|mm|middle_middle|bm|bottom_middle|tm|top_middle)
            gapX=$(( gapX - OFFSET_X ))
            ;;
        tl|top_left|ml|middle_left|bl|bottom_left)
            gapX=$(( gapX + OFFSET_X ))
            ;;
    esac
    case $align in
        tr|top_right|tl|top_left|tm|top_middle)
            gapY=$(( gapY + OFFSET_Y ))
            ;;
        br|bottom_right|bl|bottom_left|bm|bottom_middle|mm|middle_middle|ml|middle_left|mr|middle_right)
            gapY=$(( gapY - OFFSET_Y ))
            ;;
    esac
    if [[ $align = none ]];then   # placement managed by Openbox
        TXT="This Conky has 'alignment none'\nso placement is handled by the Window Manager.\n"
        $DIALOG --text="$TXT" --button="OK"
        echo -e "\nConky has 'alignment none',\nso placement is handled by the Window Manager\nExiting...\n"
        exit 0
    fi
}

$DIALOG --text="Click OK to pick a conky\nand record the conky position" \
     --button="Select Conky:0" --button="gtk-cancel:1"

if (( $? == 0 ));then
    getStart
else
    echo "  Cancelled: exiting..."
    exit 0
fi

$DIALOG --text="Move the Conky to the desired location\nthen click 'OK'" \
     --button="OK:0" --button="gtk-cancel:1"

if (( $? == 0 ));then
    getFinish
else
    echo "  Cancelled: exiting..."
    exit 0
fi

getOffset

edit_conkyfile "$CONKYPATH" "gap_x"=$gapX "gap_y"=$gapY

exit 0

Last edited by damo (2015-11-08 15:07:14)


Be Excellent to Each Other...
The Bunsenlabs Lithium Desktop » Here
FORUM RULES and posting guidelines «» Help page for forum post formatting
Artwork on DeviantArt  «» BunsenLabs on DeviantArt

Offline

#50 2015-11-09 05:25:24

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,668
Website

Re: Movable conkys

It's looking good!

Have to go out now, but a couple of things:
That awk line outputs the first word in the line, command, then the next argument after -c so if the command is conky you'll get 'conky /path/to/conffile'
So,
if grep "conky" <<< $CMD &>/dev/null;then
could be substituted with:
if [[ ${CMD%% *} = conky ]]; then
This avoids calling grep and also avoids getting a false positive if there's a "conky" somewhere else in the command.
Also CONKYPATH had better be ${CMD#* } in case someone decides to put their conffile in a directory called "My Conkys". neutral

If you take parse_conkyfile out of edit_conkyfile and run it earlier you'll already have all the config values in the config array so this:

    unset VAR VAL
    while read VAR VAL;do
        case $VAR in
            alignment)  align="$VAL";;
            gap_x    )  gapX=$VAL;;
            gap_y    )  gapY=$VAL;;
        esac
    done < <(cat $CONKYPATH)

could be this:

gapX=${config[gap_x]}
gapY=${config[gap_y]}

or just use the array directly. smile


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#51 2015-11-09 08:48:31

damo
....moderator....
Registered: 2015-08-20
Posts: 6,734

Re: Movable conkys

What would I do without you! Bash hurts my brain sad


Be Excellent to Each Other...
The Bunsenlabs Lithium Desktop » Here
FORUM RULES and posting guidelines «» Help page for forum post formatting
Artwork on DeviantArt  «» BunsenLabs on DeviantArt

Offline

#52 2015-11-09 16:03:09

xaos52
The Good Doctor
From: Planet of the @pes
Registered: 2015-09-30
Posts: 695

Re: Movable conkys

@damo:
Adding to an array is always preferable to adding to a string, so I suggest using an array for the arguments to 'sed' in function 'edit_conkyfile'. The first can be done in constant time, no matter how many emelents in the array, the latter takes more and more time as the string length increases.

Here is what I came up with for the function 'edit_conkyfile':

# usage: edit_conkyfile file name=value [name2=value2...]
# use absolute path to file
edit_conkyfile() {
    [[ "$1" = /* ]] || {
        echo "$0: $1 is not an absolute path." >&2
        return 1
    }
    file=$1
    shift
    parse_conkyfile "$file"
    local name value
    declare -ag sed_args
    while [[ $1 ]]; do
        unset name value sed_pattern sed_replace
        name="${1%%=*}"
        value="${1#*=}"
        shift
        [[ ${config["$name"]+x} ]] || {
            echo "$0: config key $name does not exist" >&2
            return 1
        }
        [[ ${config["$name"]//[[:space:]]} = "${value//[[:space:]]}" ]] && continue
        (( ${#sed_args[@]} == 0 )) && sed_args=("-ri")
        sed_pattern="^ *$name .*$"
        grep -q "#conkymove, original value for $name:" "$file" ||
            sed_replace="#conkymove, original value for $name: ${config[$name]}\n"
        sed_replace+="$name $value"
        sed_args+=("-e")
        sed_args+=("s/$sed_pattern/$sed_replace/")
    done
    (( ${#sed_args[@]} )) && sed "${sed_args[@]}" "$file"
}

Last edited by xaos52 (2015-11-09 16:26:21)

Offline

#53 2015-11-10 05:16:07

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,668
Website

Re: Movable conkys

Thanks Doc! That function was actually mine, and I appreciate your improvement. I never thought about the increasing time to add an element to a string as it gets longer.

One question, my version generates a command like:
sed -ri s/pattern1/replace1;s/pattern2/replace2;...
while yours writes:
sed -ri -e s/pattern1/replace1 -e s/pattern2/replace2 ...

Is there any difference, in execution time or anything else, between these two syntaxes?

@damo, unlike yrs truly, xaos52 is one of those real shell gurus who usually have more more advanced stuff on their plates...


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#54 2015-11-10 09:27:59

xaos52
The Good Doctor
From: Planet of the @pes
Registered: 2015-09-30
Posts: 695

Re: Movable conkys

@john
I don't think you will notice increasing execution time until the string becomes very long indeed, but I prefer using arrays when manipulating strings.

Usage of the -e pattern is a personal preference. I don't expect any differences performance-wise.
Minor differerences between sed versions. See this link

Thanks for the kind words, John.
I admire your awk skills - but try to avoid it and use bash features wherever possible.

Offline

#55 2015-11-10 09:37:10

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,668
Website

Re: Movable conkys

Damo, I added the changes I mentioned, also tweaked some functions:
getStart: use one call to xwininfo to get all the data instead of going back multiple times, don't use grep or awk.
getFinish: for symmetry, use the same method as in getStart to parse the output of xwininfo.
getOffset: use info from results of parse_conkyfile()

I've tested it once on a VM (Alt-drag doesn't work so I had to use wmctrl to move the conky) and pinning looks OK so far.  cool

#!/bin/bash
##
#   Script to set the position of a moveable Conky
#
#   Written by damo <damo@bunsenlabs.org> November 2015
#   with major contributions of functions, commands and suggestions by @johnraff

DIALOG="yad --center --undecorated --borders=20 \
--window-icon=/usr/share/pixmaps/Bunsenlabs-flame-256.svg"

unset CONKYPATH posX_1 posY_1 posX_2 posY_2 OFFSET_X OFFSET_Y gapX gapY

# makes array "config"
parse_conkyfile(){   # function by @johnraff
    [[ -f $1 ]] || { echo "$1 is not a file." >&2;return 1;}
    unset config
    declare -Ag config
    local name value
    while read name value
    do
        [[ $name ]] || continue
        [[ $name = TEXT* ]] && break
        config["$name"]="$value"
    done < <(sed 's/\#.*$//' "$1")
}


# usage: edit_conkyfile file name=value [name2=value2...]
# use absolute path to file
# parse_conkyfile should already have been run
edit_conkyfile() {  # function by @johnraff, improved by xaos52
    [[ "$1" = /* ]] || {
        echo "$0: $1 is not an absolute path." >&2
        return 1
    }
    file=$1
    shift
    local name value
    declare -ag sed_args
    while [[ $1 ]]; do
        unset name value sed_pattern sed_replace
        name="${1%%=*}"
        value="${1#*=}"
        shift
        [[ ${config["$name"]+x} ]] || {
            echo "$0: config key $name does not exist" >&2
            return 1
        }
        [[ ${config["$name"]//[[:space:]]} = "${value//[[:space:]]}" ]] && continue
        (( ${#sed_args[@]} == 0 )) && sed_args=("-ri")
        sed_pattern="^ *$name .*$"
        grep -q "#conkymove, original value for $name:" "$file" ||
            sed_replace="#conkymove, original value for $name: ${config[$name]}\n"
        sed_replace+="$name $value"
        sed_args+=("-e")
        sed_args+=("s/$sed_pattern/$sed_replace/")
    done
    (( ${#sed_args[@]} )) && sed "${sed_args[@]}" "$file"
}

function getStart(){    #   Get initial Conky position
    unset CONKYPATH
    unset info1
    declare -A info1
    while read line
    do
        unset key value
        [[ $line =~ Window\ id: ]] && {
            ID=${line#*id:}
            ID=${ID% \"*}
        }
        [[ $line != xwininfo:* && $line = *:* ]] && {
            key=${line%:*}
            value=${line#*:}
            info1[$key]=$value
        }
    done < <(xwininfo)
    # info now contains all the output of xwininfo

    # command suggested by @johnraff....
    CMD=$(xprop -id $ID  WM_COMMAND | awk -F '", "' '{cmd=$1;sub(/^.*{ "/,"",cmd);for (i=1;i<=NF;i++)if($i=="-c"){i++;sub(/\" }$/,"",$i);gsub(/\\\"/,"\"",$i);print cmd,$i;exit}}')

    if [[ ${CMD%% *} = conky ]];then
        echo "Found a conky"
        CONKYPATH=${CMD#* }
        posX_1=${info1[Absolute upper-left X]}
        posY_1=${info1[Absolute upper-left Y]}
    else
        echo "Selection is not a conky"
        $DIALOG --button="OK:0" --text="Selection is not a conky\n\nChoose again"
        getStart
    fi
}

function getFinish(){   #   Get new Conky position
    unset info2
    declare -A info2
    while read line
    do
        unset key value
        [[ $line != xwininfo:* && $line = *:* ]] && {
            key=${line%:*}
            value=${line#*:}
            info2[$key]=$value
        }
    done < <(xwininfo -id $ID)
    posX_2=${info2[Absolute upper-left X]}
    posY_2=${info2[Absolute upper-left Y]}
}

function getOffset(){   # parse_conkyfile should already have been run
    if [[ ${config[alignment]} = none ]];then   # placement managed by Openbox
        TXT="This Conky has 'alignment none'\nso placement is handled by the Window Manager.\n"
        $DIALOG --text="$TXT" --button="OK"
        echo -e "\nConky has 'alignment none',\nso placement is handled by the Window Manager\nExiting...\n"
        exit 0
    fi

    OFFSET_X=$(( posX_2 - posX_1 ))
    OFFSET_Y=$(( posY_2 - posY_1 ))

    case ${config[alignment]} in
        tr|top_right|mr|middle_right|br|bottom_right|mm|middle_middle|bm|bottom_middle|tm|top_middle)
            gapX=$(( ${config[gap_x]} - OFFSET_X ))
            ;;
        tl|top_left|ml|middle_left|bl|bottom_left)
            gapX=$(( ${config[gap_x]} + OFFSET_X ))
            ;;
    esac
    case ${config[alignment]} in
        tr|top_right|tl|top_left|tm|top_middle)
            gapY=$(( ${config[gap_y]} + OFFSET_Y ))
            ;;
        br|bottom_right|bl|bottom_left|bm|bottom_middle|mm|middle_middle|ml|middle_left|mr|middle_right)
            gapY=$(( ${config[gap_y]} - OFFSET_Y ))
            ;;
    esac
}

$DIALOG --text="Click OK to pick a conky\nand record the conky position" \
     --button="Select Conky:0" --button="gtk-cancel:1"

if (( $? == 0 ));then
    getStart
else
    echo "  Cancelled: exiting..."
    exit 0
fi

$DIALOG --text="Move the Conky to the desired location\nthen click 'OK'" \
     --button="OK:0" --button="gtk-cancel:1"

if (( $? == 0 ));then
    getFinish
else
    echo "  Cancelled: exiting..."
    exit 0
fi

parse_conkyfile "$CONKYPATH"

getOffset

edit_conkyfile "$CONKYPATH" "gap_x"=$gapX "gap_y"=$gapY

exit 0

...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#56 2015-11-10 14:29:10

xaos52
The Good Doctor
From: Planet of the @pes
Registered: 2015-09-30
Posts: 695

Re: Movable conkys

@john
Here is a modified version of the 'check' function you posted in post #47
Avoiding awk to get the correct path to a conky and some comments  thrown in:

check() {
    echo "Enter FUDGE FACTOR"
    read -r
    fudge=$REPLY
    echo "FUDGE FACTOR is set at ${fudge}px"
    screen_dims=$(xrandr --current | awk '/\*/{print $1}')
    echo "Screen dimensions: $screen_dims"$'\n'
    unset win
    declare -A win
    while read win[id] win[desktop] win[xoffset] win[yoffset] win[width] win[height] win[client] win[title]
    do
        unset cmd_file
        [[ ${win[title]} = *[Cc]onky* ]] || continue
        # cmd_file=$(xprop -id ${win[id]}  WM_COMMAND | awk -F '", "' '{cmd=$1;sub(/^.*{ "/,"",cmd);for (i=1;i<=NF;i++)if($i=="-c"){i++;sub(/\" }$/,"",$i);gsub(/\\\"/,"\"",$i);print cmd,$i;exit}}')
        cmd_file=$(xprop -id ${win[id]}  WM_COMMAND)
        # skip if xprop returns id not found - window was closed in the time gap between
        # running wmctrl and xprop
        # or
        # you have firefox open on a page with 'conky' in its title
        [[ "$cmd_file" == *not\ found* ]] && {
            echo "ID:${win[id]} - $cmd_file"
            continue
        }
        # remove prefix up to the space after the opening {
        cmd_file=${cmd_file#*\{ }
        # remove suffix space and closing }
        cmd_file=${cmd_file% \}}
        # read the string into an array
        # IFS=", " mapfile <<< "$cmd_file" does not seem to work, so
        # replace every occurrence of ', ' by a new_line
        cmd_file=${cmd_file//, /$'\n'}
        mapfile -t helper <<< "$cmd_file"
        # conky command. can be conky, /usr/bin/conky, usr/local/bin/conky, ...
        [[ ${helper[0]} == *conky* ]] || continue
        # remove leading and trailing double quote from the array elements
        # set cfgfile
        index_cfgfile=0
        for ((i=0; i<${#helper[@]}; i++)) 
        do
            local entry
            entry=${helper[i]}
            entry=${entry#\"}
            entry=${entry%\"}
            helper[$i]="$entry"
            [[ "$entry" == "-c"  ]] && index_cfgfile=$((i+1))
        done
        (( $index_cfgfile )) && cfgfile="${helper[index_cfgfile]}" || cfgfile="$HOME/.conkyrc"
        unset index_cfgfile
        unset helper
        conky2xy "$cfgfile"
        echo "ID: ${win[id]}
Title: ${win[title]}
File: $cfgfile
Calculated from config file, X: ${config[xoffset]}
Position from Wmctrl, X: ${win[xoffset]}
Calculated from config file, Y: ${config[yoffset]}
Position from Wmctrl, Y: ${win[yoffset]}
"
    done < <(wmctrl -lG)
}

Offline

#57 2015-11-10 15:13:10

xaos52
The Good Doctor
From: Planet of the @pes
Registered: 2015-09-30
Posts: 695

Re: Movable conkys

Oh, and there is this: alway use

read -r ...

because

read without -r

Essentially all you need to know about -r is to ALWAYS use it. The exact behavior you get without -r is completely useless even for weird purposes. It basically allows the escaping of input which matches something in IFS, and also escapes line continuations. It's explained pretty well in the POSIX read spec.

See this link.

Last edited by xaos52 (2015-11-10 15:27:58)

Offline

#58 2015-11-11 22:20:01

damo
....moderator....
Registered: 2015-08-20
Posts: 6,734

Re: Movable conkys

The $CMD awk construction doesn't work if other switches are used in combination with "-c"

CMD=$(xprop -id $ID  WM_COMMAND | awk -F '", "' '{cmd=$1;sub(/^.*{ "/,"",cmd);for (i=1;i<=NF;i++)if($i=="-c"){i++;sub(/\" }$/,"",$i);gsub(/\\\"/,"\"",$i);print cmd,$i;exit}}')

This command will run a conky with spaces in the path (`-cq` doesn't run BTW):

conky -qc "/home/damo/.config/conky/conky Test/ellipses.conkyrc"

...but then the awk fails to find `($i=="-c"), so the default conky starts instead.


Be Excellent to Each Other...
The Bunsenlabs Lithium Desktop » Here
FORUM RULES and posting guidelines «» Help page for forum post formatting
Artwork on DeviantArt  «» BunsenLabs on DeviantArt

Offline

#59 2015-11-11 22:31:57

Sector11
Mod Squid Tpyo Knig
From: Upstairs
Registered: 2015-08-20
Posts: 8,030

Re: Movable conkys

    conky -c /home/sector11/testconky/conkyrc1 &
    conky -c /home/sector11/testconky/conkyrc2 &
    conky -c /home/sector11/testconky/conkyrc3 &

Didn't work with these either.

Other than alignment and the gaps, well, and the # in the filename - they are the same:

1

# pkill -xf "conky -c /home/sector11/testconky/conkyrc1" &
##  Default conky
###  Begin Window Settings  ##################################################
# Create own window instead of using desktop (required in nautilus)
own_window yes
own_window_type normal
own_window_transparent no #yes  ## see: ARGB below
own_window_hints undecorated,below,skip_taskbar,skip_pager
own_window_colour 000000
own_window_class Conky
own_window_title Conky
### ARGB can be used for real transparency
### NOTE that a composite manager is required for real transparency.
### This option will not work as desired (in most cases) in conjunction with
### own_window_type normal
 own_window_argb_visual yes

### When ARGB visuals are enabled, this use this to modify the alpha value
### Use: own_window_type normal
### Use: own_window_transparent no
### Valid range is 0-255, where 0 is 0% opacity, and 255 is 100% opacity.
 own_window_argb_value 0

# Use the Xdbe extension? (eliminates flicker)
# It is highly recommended to use own window with this one
# so double buffer won't be so big.
double_buffer yes

minimum_size 160 0     ## width, height
#maximum_width 160       ## width

gap_x 120 # left-right
gap_y 10 # up-down

alignment tl
###################################################  End Window Settings  ###
###  Font Settings  #########################################################
# Use Xft (anti-aliased font and stuff)
use_xft yes
xftfont monospace:bold:size=9

# Alpha of Xft font. Must be a value at or between 1 and 0 ###
xftalpha 1
# Force UTF8? requires XFT ###
override_utf8_locale yes

uppercase no
######################################################  End Font Settings  ###
###  Color Settings  #########################################################
draw_shades yes
default_shade_color 000000
draw_outline no
default_outline_color 000000

default_color DCDCDC #Gainsboro
color0 A9A9A9 #DarkGray
color1 778899 #LightSlateGray
color2 F5F5DC #Beige
color3 87CEFA #LightSkyBlue
color4 48D1CC #MediumTurquoise
color5 FFDEAD #NavajoWhite
color6 00BFFF #DeepSkyBlue
color7 B0E0E6 #PowderBlue
color8 FFD700 #Gold
color9 FFA07A #LightSalmon
#####################################################  End Color Settings  ###
###  Borders Section  ########################################################
draw_borders no
# Stippled borders?
stippled_borders 0
# border margins
border_inner_margin 3
border_outer_margin 0
# border width
border_width 1
# graph borders
draw_graph_borders yes
#default_graph_size 15 40
#####################################################  End Borders Secton  ###
###  Miscellaneous Section  ##################################################
# Boolean value, if true, Conky will be forked to background when started.
background yes

# Adds spaces around certain objects to stop them from moving other things
# around, this only helps if you are using a mono font
# Options: right, left or none
use_spacer none

# Default and Minimum size is 256 - needs more for single commands that
# "call" a lot of text IE: bash scripts
# text_buffer_size 1028

# Subtract (file system) buffers from used memory?
no_buffers yes

# change GiB to G and MiB to M
short_units yes

# Like it says, ot pads the decimals on % values
# doesn't seem to work since v1.7.1
pad_percents 2

#   Maximum size of user text buffer, i.e. layout below TEXT line in config file
#  (default is 16384 bytes)
# max_user_text 16384

# Desired output unit of all objects displaying a temperature. Parameters are
# either "fahrenheit" or "celsius". The default unit is degree Celsius.
# temperature_unit Fahrenheit

##############################################  End Miscellaneous Section  ###
update_interval 1

TEXT
${time %X}${alignr 5}${uptime_short}
${alignc}${time %x}
${membar 0}
${alignc}${kernel}
${membar 0}
Host${alignr 5}${nodename}

RAM${alignr 5}${mem} / ${memmax}
Swap${alignr 5}${swap} / ${swapmax}
Disk${alignr 5}${fs_used /} / ${fs_size /}

CPU 1${alignr 5}${cpu cpu1}%
CPU 2${alignr 5}${cpu cpu2}%
CPU 3${alignr 5}${cpu cpu3}%
CPU Avg${alignr 5}${cpu cpu0}%

/Root: ${fs_size /}${alignr 5}${fs_used_perc /}%${color}
/Home: ${fs_size /home}${alignr 5}${fs_used_perc /home}%

DISK ${membar 0}
Read:${alignr 5}${diskio_read /dev/sda}
Write:${alignr 5}${diskio_write /dev/sda}

NETWORK ${membar 0}

Down:${alignr 5}${downspeedf eth0}
${alignc}${downspeedgraph eth0 14,140 000000 ff0000}

Up:${alignr 5}${upspeedf eth0}
${alignc}${upspeedgraph eth0 14,140 000000 00ff00}


Using hr
line ${hr}
     Vertical spacing off
line ${hr}

Using membar 0
line ${membar 0}
     Best vertical spacing
line ${membar 0}

2

gap_x 0 # left-right
gap_y 10 # up-down

alignment tm

3

gap_x 120 # left-right
gap_y 10 # up-down

alignment tr

Debian 12 Beardog, SoxDog and still a Conky 1.9er

Offline

#60 2015-11-11 22:58:10

damo
....moderator....
Registered: 2015-08-20
Posts: 6,734

Re: Movable conkys

This awk regex construction seems to work in the `CMD=` line:

CMD=$(xprop -id $ID  WM_COMMAND | awk -F '", "' '{cmd=$1;sub(/^.*{ "/,"",cmd);for (i=1;i<=NF;i++)if($i ~ /-([a-z])?c/){i++;sub(/\" }$/,"",$i);gsub(/\\\"/,"\"",$i);print cmd,$i;exit}}')

I t is meant to cope with "-" + "any alpha chars" + "c"


Be Excellent to Each Other...
The Bunsenlabs Lithium Desktop » Here
FORUM RULES and posting guidelines «» Help page for forum post formatting
Artwork on DeviantArt  «» BunsenLabs on DeviantArt

Offline

Board footer

Powered by FluxBB