Contrôle de la version du code entre les fichiers locaux et les réponses de l'UA

2

Introduction

Notez qu’il s’agit d’une question à laquelle il faut répondre pour partager des connaissances.

Un script "bash only" est nécessaire pour télécharger Ask Ubuntu réponses liées au code source (scripts) sur mon système. Ensuite, comparez les deux en utilisant la commande diff .

L’objectif est de savoir si mon code a été modifié et que les réponses de AU doivent être mises à jour ou si une personne a révisé une réponse de l’AU que j’ai postée et que je dois transférer ces modifications dans mon code.

    
posée WinEunuuchs2Unix 05.04.2017 - 05:27
la source

2 réponses

3

websync script

#!/bin/bash

# NAME: websync

# Must have the yad package.
command -v yad >/dev/null 2>&1 || { echo >&2 \ 
  "yad package required but it is not installed.  Aborting."; \
  exit 99; }

RenumberListArr () {

IFS='|'

ListArrCnt=${#ListArr[@]}

i=1 # First array element (0) is "false", followed by record number element (1)
j=1 # All Record numbers count starting at 1

while [ $i -lt $ListArrCnt ] ; do
    ListArr[$i]=$j
    j=$(($j + 1))
    i=$(($i + $RecArrCnt))
done

} # RenumberListArr ()

ColSelect=0
ColRecNo=1
ColFileDate=2
ColFileName=3
ColStatus=4Address
ColAnsDate=5
ColA_Votes=5
ColWebAddr=6
ColQ_Votes=7
ColTitle=8

NewFileDate=0
NewFileName=1
NewStatus=2
NewAnsDate=3
NewA_Votes=3
NewWebAddr=4
NewQ_Votes=5
NewTitle=6

LineOut=""
HTMLtoText () {
    LineOut=  # Parm 1= Input line
    LineOut="${LineOut//&/&}"
    LineOut="${LineOut//&lt;/<}"
    LineOut="${LineOut//&gt;/>}"
    LineOut="${LineOut//&quot;/'"'}"
    LineOut="${LineOut//&#39;/"'"}"
    LineOut="${LineOut//&ldquo;/'"'}"
    LineOut="${LineOut//&rdquo;/'"'}"
} # HTMLtoText ()


Ampersand=$'6'
Equals="================================================================================="
Dashes="---------------------------------------------------------------------------------"
AnswerID=""
PercentFile="/tmp/websync-percent" # Temp file used for progress bar percentage

UpdateEntry () {

# PARM: 1=ONE display msgs, else file name for messages.

if [[  == "ONE" ]] ; then
    bDisplayMsgs=true
    MsgFileName=""  # In case a single update follows all update
else
    bDisplayMsgs=false
    MsgFileName=""
fi

local BarNo="2"

# $RecArr[@] must be populated

# Searches in order they are found in an answer
SearchTitle=true
FoundTitle=false
SearchQ_Vote=true
FoundQ_Vote=false
SearchA_Vote=true
FoundA_Vote=false
FoundLine1=false
FoundLine2=false
FoundLine3=false
EndOfFile=false
AnswerWritten=false

AnswerID=$(echo ${RecArr[$ColWebAddr]} | rev | cut -d# -f1 | rev)

# Get file modified date in human readable format using STAT
RecArr[$ColFileDate]=$(stat "${RecArr[$ColFileName]}" | \
        grep "Modify:"| cut -f2 -d" ")

HoldIFS="$IFS"
IFS=$'\n'       # make newlines the only separator

AnswerSize=$(stat -c%s "/tmp/$AnswerID")

# If answer size less < 1000 then wget failed.
if [[ $AnswerSize -lt 1000 ]] ; then
    yad --error --center \
    --text="wget failed to download answer from Stack Exchange."
    RecArr[$ColA_Status]="Answer < 1K"
    IFS="$HoldIFS"
    return 1
fi

FirstThreeLines=()

FirstThreeLines=( $(head -n10 ${RecArr[$ColFileName]}) )

AnswerLines=0
AllLinesSize=0
LastPercent=0
fPrintNextLine=false # Use this for tracing HTML and displaying Line

echo $BarNo:0 > "$PercentFile" # Just in case last time temp file wasn't removed

fEOFskip=false

while IFS= read -r Line; do

AnswerLines=$(( ++AnswerLines ))
AllLinesSize=$(( $AllLinesSize+${#Line} ))

if [[ $Line == *"$Ampersand""lt;/code$Ampersand""gt;"* ]] ; then
    # Answer contains </code> in text section, it's a fake End of Code tag.
    fEOFskip=true
else
    fEOFskip=false
fi

# Convert HTML codes to normal characters

HTMLtoText $Line
Line="$LineOut"

Percent=$(( $AllLinesSize * 100 / $AnswerSize ))
if [[ "$Percent" -ne "$LastPercent" ]] ; then
    LastPercent=$Percent
    # Send percentage via working file to spawned process with yad progress bar
    echo $BarNo:$Percent > "$PercentFile"
fi

if [ $fPrintNextLine = true ] ; then
    echo "Line at start: $Line"
fi

# Parse Line: </script> <dev id="question-header">

if [ $SearchTitle = true ] ; then
    if [[ $Line == *"<div id=\"question-header\">"* ]] ; then SearchTitle=false ; fi
    continue
fi

if [ $SearchTitle = false ] && [ $FoundTitle = false ] ; then
    if [[ $Line == *"<h1 itemprop=\"name\""* ]] ; then
        FoundTitle=true
        Title=$(cut -d ">" -f 3 <<< "$Line")
        Title=$(cut -d "<" -f 1 <<< "$Title")
        HTMLtoText $Title
        RecArr[$ColTitle]="$LineOut"
    fi
    continue
fi

if [ $SearchQ_Vote = true ] ; then
    if [[ $Line == *"<div class=\"question\""* ]] ; then SearchQ_Vote=false ; fi
    continue
fi

if [ $SearchQ_Vote = false ] && [ $FoundQ_Vote = false ] ; then
    if [[ $Line == *"<span itemprop=\"upvoteCount\""* ]] ; then
        FoundQ_Vote=true
        QuestionVotes=$(cut -d ">" -f 2 <<< "$Line")
        QuestionVotes=$(cut -d "<" -f 1 <<< "$QuestionVotes")
        RecArr[$ColQ_Votes]=$QuestionVotes
    fi
    continue
fi

# Parse lines: <a name="894470"></a>
# <div id="answer-894470" class="answer" data-answerid="894470"  itemscope
#  itemtype="http://schema.org/Answer">

if [ $SearchA_Vote = true ] ; then
    if [[ $Line == *"<div id=\"answer-$AnswerID\""* ]]; then SearchA_Vote=false ; fi
    continue
fi

if [ $SearchA_Vote = false ] && [ $FoundA_Vote = false ] ; then
    if [[ $Line == *"span itemprop=\"upvoteCount\""* ]] ; then
        FoundA_Vote=true
        # We don't have array entries setup yet so store in working variable
        AnswerVotes=$(cut -d ">" -f 2 <<< "$Line")
        AnswerVotes=$(cut -d "<" -f 1 <<< "$AnswerVotes")
        RecArr[$ColA_Votes]=$AnswerVotes
    fi
    continue
fi

if [ $FoundLine1 = false ] ; then
    if [[ $Line == *"${FirstThreeLines[0]}"* ]] ; then # May have <code> prefix
        FoundLine1=true
        # Create file with first line taken from "clean" bash array
        echo "${FirstThreeLines[0]}" > /tmp/websync-webfile
    fi
    continue
fi

if [ $FoundLine1 = true ] && [ $FoundLine2 = false ]; then
    # Empty lines aren't in our array so skip test if in web file
    if [[ $Line == "" ]] ; then 
        echo "$Line" >> /tmp/websync-webfile # Append empty line
        continue
    fi
    if [[ $Line == "${FirstThreeLines[1]}" ]] ; then # Line 2 match exactly?
        FoundLine2=true
        echo "$Line" >> /tmp/websync-webfile # Append second line
    else
        # Line 2 doesn't match so force search to restart at line 1
        FoundLine1=false
    fi
    continue
fi

if [ $FoundLine2 = true ] && [ $FoundLine3 = false ]; then
    # Empty lines aren't in our array so skip test if in web file
    if [[ $Line == "" ]] ; then 
        echo "$Line" >> /tmp/websync-webfile # Append empty line
        continue
    fi
    if [[ $Line == "${FirstThreeLines[2]}" ]] ; then # Line 3 match exactly?
        FoundLine3=true
        echo "${FirstThreeLines[2]}" >> /tmp/websync-webfile # Append third line
    else
        # Line 3 doesn't match so force search to restart at line 1
        FoundLine1=false
        FoundLine2=false
    fi
    continue
fi

# We are only here when first three code lines have matched up in Stack Exchange.
if [ $EndOfFile = false ] ; then
    if [[ $Line == *"</code>"* ]] && [[ $fEOFskip == false ]] ; then
        EndOfFile=true
    else
        echo "$Line" >> /tmp/websync-webfile
    fi
fi

if [ $fPrintNextLine = true ] ; then
    echo "Line at end: $Line"
    fPrintNextLine=false
elif [[ $Line == *"---- ENTER SEARCH STRING HERE ----"* ]] ; then
    fPrintNextLine=true
fi

done < "/tmp/$AnswerID"

echo $BarNo:100 > "$PercentFile" # force spawned yad progress bar to close

if [[ ! -f "${RecArr[$ColFileName]}" ]] ; then   # File exists?
    yad --error --center --text "${RecArr[$ColFileName]} does not exist."
    RecArr[$ColStatus]="Bad File"
elif [[ ! -s "${RecArr[$ColFileName]}" ]] ; then  # File not empty?
    yad --error --center --text "${RecArr[$ColFileName]} is empty."
    RecArr[$ColStatus]="Empty File"
fi

if [ $FoundLine1 = true ] && [ $FoundLine2 = true ] && [ $FoundLine3 = true ]; then
    FileDiff="/tmp/websync-diff-"$(date +%s)
    if [[ "$MsgFileName" != "" ]] ; then
        echo $Equals >> $MsgFileName
    fi
    diff --unified=2 -w -b -B -I --suppress-blank-empty \
        --ignore-tab-expansion --suppress-common-lines --ignore-all-space \
        ${RecArr[$ColFileName]} /tmp/websync-webfile > $FileDiff

    # If file doesn't exist, errors in diff parameters
    # If file size =0 there were no differences
    if [[ -f $FileDiff ]] ; then
        if [[ -s $FileDiff ]] ; then
            if [[ $bDisplayMsgs == true ]] ; then
                # File not empty.
                gedit $FileDiff
            else
                cat $FileDiff >> $MsgFileName
            fi
            RecArr[$ColStatus]="Different"
        else
            if [[ $bDisplayMsgs == true ]] ; then
                yad --info --center --text \
                    "Code in ${RecArr[$ColFileName]} matches on Stack Exchange."
            else
                echo "Code in ${RecArr[$ColFileName]} matches on Stack Exchange." \
                     >> $MsgFileName
                echo $Dashes >> $MsgFileName
            fi
            RecArr[$ColStatus]="Matches"
        fi
    else
        yad --error --center --text "websync - Error in 'diff' parameters."
        RecArr[$ColStatus]="Diff Parameter Error"
    fi
else
    if [[ $bDisplayMsgs == true ]] ; then
        yad --error --center --text \
        "First three lines of ${RecArr[$ColFileName]} not found on Stack Exchange."
    else
        echo $Equals >> $MsgFileName
        echo "First three lines of ${RecArr[$ColFileName]} not found on Stack Exchange." \
             >> $MsgFileName
        echo $Dashes >> $MsgFileName
    fi
    RecArr[$ColStatus]="3 lines not found"
fi

IFS="$HoldIFS"

# Remove Work files
rm "/tmp/$AnswerID"
rm /tmp/websync-webfile
rm "$PercentFile"
rm "$FileDiff"

return 0

} # UpdateEntry ()


UpdateOne () {

# $RecArr[@] must be populated

# = ONE or $MsgFileName
# = Bar 1
# Download stack exchange answer 
AnswerID=$(echo ${RecArr[$ColWebAddr]} | rev | cut -d# -f1 | rev) # Answer# for file name

local BarNo="1"
echo "$BarNo:10"    > "$PercentFile" # Zero percent complete
echo "$BarNo:#Downloading with wget." > "$PercentFile"

wget -O- "${RecArr[$ColWebAddr]}" > "/tmp/$AnswerID"
if [[ "$?" -ne 0 ]]               # check return code for errors
  then
    # Sometimes a second attempt is required. Not sure why.
    wget -O- "${RecArr[$ColWebAddr]}" > "/tmp/$AnswerID"
fi
if [[ "$?" == 0 ]]               # check return code for errors
  then
      echo "$BarNo:100" > "$PercentFile"
      echo "$BarNo:#Download completed." > "$PercentFile"
  else
      echo "$BarNo:100" > "$PercentFile"
      echo "$BarNo:#Download error." > "$PercentFile"
      echo "ERROR: $AnswerID" >> ~/websync.log
      return 1
fi

UpdateEntry 
ret=$?
if [[ $ret != 0 ]] ; then
    # We weren't able to anayze SE answer -- too small
    return 1
fi

((TransCount++))            # Update count of changes

# Update array entry
let i=1
while [[ $i -lt $ListArrCnt ]] ; do
    if [[ ${ListArr[i]} == ${RecArr[1]} ]] ; then
        # We have matching record number
        ListArr[++i]="${RecArr[$ColFileDate]}"
        ListArr[++i]="${RecArr[$ColFileName]}" # File name should never change
        ListArr[++i]="${RecArr[$ColStatus]}"
        ListArr[++i]="${RecArr[$ColA_Votes]}"
        ListArr[++i]="${RecArr[$ColWebAddr]}"
        ListArr[++i]="${RecArr[$ColQ_Votes]}"
        ListArr[++i]="${RecArr[$ColTitle]}"
        let i=$(($ListArrCnt + 1)) # force exit from while loop
    else
        let i=$(($i + $RecArrCnt)) # Check next entry
    fi
done

return 0

} # UpdateOne ()


RecSelected=true # Overrides are below
UpdateAllOrOne () {

TITLE="websync"                             # dialog title
TEXT="<b>Update Entry</b> ${RecArr[$ColFileName]}"     # dialog text
ICON="emblem-downloads"                     # window icon (appears in launcher)
IMAGE="browser-download"                    # window image (appears in dialog)

# Process a single entry
if [[ $RecSelected == true ]] ; then

    echo "2:0" > "$PercentFile" # Just in case last time temp file wasn't removed

    # Repurpose yad progress bar as wget information message.
    CurrentEntry="${RecArr[$ColFileName]}"
    ( spawn-progress-multi $PercentFile \
        '--multi-progress --center --auto-close --skip-taskbar --title "websync" --text "Update Entry $CurrentEntry" --window-icon $ICON --image $IMAGE --fixed --width=600 --height=200 --watch-bar2 --bar=Downloading:NORM --bar=Analyzing:NORM' \
         2 & )

    UpdateOne ONE

    echo "2:100" > "$PercentFile" # Force progress display to shut down

    return $?
fi

MsgFileName="/tmp/websync-diff-"$(date +%s)
echo "--- /Prefix for files on local drive" > $MsgFileName
echo "+++ /Prefix for code in Stack Exchange answers" >> $MsgFileName

echo "3:0" > "$PercentFile" # Just in case last time temp file wasn't removed

# Repurpose yad progress bar as wget information message.
CurrentEntry="${RecArr[$ColFileName]}"
( spawn-progress-multi $PercentFile \
    "--multi-progress --center --auto-close --skip-taskbar --title "websync" --text '"'Update All Entries '"' --window-icon $ICON --image $IMAGE --fixed --width=1000 --height=200 --watch-bar3 --bar=Downloading:NORM --bar=Analyzing:NORM --bar='"'Entry progress'"':NORM" \
         3 & )

# Process all Entries
local let k=0
RecArr[0]=false
EndLoop=$(( ListArrCnt - 1 ))
while [ $k -lt $EndLoop ] ; do
    let i=k
    RecArr[$ColRecNo]="${ListArr[++i]}"
    RecArr[$ColFileDate]="${ListArr[++i]}"
    RecArr[$ColFileName]="${ListArr[++i]}"
    RecArr[$ColStatus]="${ListArr[++i]}"
    RecArr[$ColA_Votes]="${ListArr[++i]}"
    RecArr[$ColWebAddr]="${ListArr[++i]}"
    RecArr[$ColQ_Votes]="${ListArr[++i]}"
    RecArr[$ColTitle]="${ListArr[++i]}"

    echo "2:0" > "$PercentFile"
    echo "3:"$(( $k*100/$ListArrCnt )) > "$PercentFile"
    echo "3:#""${RecArr[$ColFileName]}" > "$PercentFile"

    UpdateOne "$MsgFileName"
    [[ "$?" != "0" ]] && return "$?" ; # clicked close on progress dialog or wget error

    let k=$(($k + $RecArrCnt)) # next entry
    if [ $k -ge $EndLoop ] ; then
        echo "3:100" > "$PercentFile"
    fi
done

# If file doesn't exist, errors in diff parameters
# If file size =0 there were no differences
if [[ -f $MsgFileName ]] && [[ -s $MsgFileName ]] ; then
    gedit $MsgFileName
fi

return 0

} # UpdateAllOrOne ()


ExternalSortArray () {

# Called on Save
cp --preserve ~/.websync ~/.websync~ #Make backup copy

IFS="|" read -ra ListArr < ~/.websync
ListArrCnt=${#ListArr[@]}
# echo "ListArrCnt: $ListArrCnt"

# Can't sort empty file or array with 1 entry
[[ $ListArrCnt -lt $(( $RecArrCnt + 1 )) ]] && return 0;

# Create Keys Index
echo " "
echo "1. Create Keys-Index Pairs File"
> ~/.websyncSort    # Empty existing file.

time for (( i=0; i<$ListArrCnt; i=i+$RecArrCnt )) ; do
    # Sort key = Question Title + Local File Name
    CurrKey="${ListArr[$(( $i + $ColTitle))]}${ListArr[$(( $i + $ColFileName))]//[^[:alnum:]\/]/}"
    echo "$CurrKey|$i" >> ~/.websyncSort
done

# Call external sort program
echo " "
echo "2. Sort Keys-Index Pairs File"
time sort -k1 -t"|" ~/.websyncSort -o ~/.websyncSort
# cat ~/.websyncSort

# Strip out keys
echo " "
echo "3. Strip out keys leaving Sorted Indices"
time cut -f2 -d '|' ~/.websyncSort > ~/.websyncNdx
# cat ~/.websyncNdx

echo " "
echo "4. Rewrite List Array by Sorted Index"
> ~/.websync    # Empty existing ListArr[] file.
RecNo=1         # Sequential record number

Second=""
time while read -r line; do 
    j=$(( $line + $RecArrCnt ))
    FldNdx=0
    for (( i=$line; i<j; i++ )); do
        LastChar="${ListArr[i]}"
        if [[ $FldNdx == $ColRecNo ]] ; then
            echo -n "$Second""$RecNo"    >> ~/.websync
            RecNo=$(( $RecNo + 1 ))
        else
            echo -n "$Second""$LastChar" >> ~/.websync
        fi
        Second="|"
        FldNdx=$(( $FldNdx + 1 ))

        # Update progress display
    done
done < ~/.websyncNdx

echo " "
printf "* * *  ExternalSortArray -- "
echo " Total elements: $ListArrCnt  * * *"

} ### ExternalSortArray ()

OldIFS="$IFS"
IFS="|"
ListArr=()

IFS="|" read -ra ListArr < ~/.websync

# Define variables for easy reading and fewer code line changes when expanding
RecArrCnt=9
ListArrCnt=${#ListArr[@]}

if [[ $ListArrCnt -lt $RecArrCnt ]] ; then
    # Handle empty file: Create dummy entries.
    ListArr+=("false" "1" "Update" "/boot/grub/grub.cfg" "Different" "Update")
    ListArr+=("https://ubuntuplace.info/questions/64149/differents-fichiers-grub-modifier")
    ListArr+=("Update" "Dummy question.")
    ListArr+=("false" "2" "Update" "$HOME/.bashrc" "Different" "Update")
    ListArr+=("https://ubuntuplace.info/questions/118573/comment-reparer-le-terminal")
    ListArr+=("Update" "Dummy question.")
    ListArrCnt=${#ListArr[@]}
fi

TransCount=0 # Number of Inserts, Edits and Deletes

ButnView=10
ButnInsert=20
ButnEdit=30
ButnDelete=40
ButnUpdate=50
ButnCancel=60
ButnSave=80

while true ; do

if [[ $TransCount -eq 0 ]] ; then
    VariableCloseText="_Close"
else
    VariableCloseText="_Cancel ALL"
fi

# adjust width & height below for your screen 1600x800 default for 1920x1080 HD
# screen and adjust font="14" below if blue title text is too small or too large.

Record=('yad --list --separator="|" --skip-taskbar \
    --title="websync - Compare code to answer posted on Stack Exchange." \
    --text="Click column heading to sort.\
    Select an entry before clicking: View / Insert / Edit / Delete / Update" \
    --width=1600 --height=800 --center --radiolist --grid-lines=both --no-markup \
    --button="_View":$ButnView     --button="_Insert before":$ButnInsert \
    --button="_Edit":$ButnEdit     --button="_Delete":$ButnDelete \
    --button="_Update":$ButnUpdate --button="$VariableCloseText":$ButnCancel \
    --button="_Save":$ButnSave \
    --search-column=3        --column "Select"       --column "Record Number":HD \
    --column "File Date":HD  --column "File Name":FL --column "Status" \
    --column "A+"            --column "Stack Exchange":HD \
    --column "Q+"            --column "Question Title" \
    "${ListArr[@]}"')
Action=$?

RecSelected=false
RecArr=()
i=0

for Field in "${Record[@]}" ; do
    RecSelected=true
    RecArr[i++]=$Field
done

# Error checking
if [[ $Action == $ButnView ]] || [[ $Action == $ButnInsert ]] || [[ $Action == $ButnEdit ]] \
|| [[ $Action == $ButnDelete ]] ; then
    if [[ $RecSelected == false ]] ; then
    yad --error --text 'You must select a record before clicking: View / Insert / Edit / Delete.' --center
    continue
    fi
fi

# Insert before || or Edit ?
if [ $Action == $ButnInsert ] || [ $Action == $ButnEdit ] ; then

    # After changing file name or Stack Exchange Address these must be updated.
    RecArr[$ColFileDate]="Update"
    RecArr[$ColStatus]="Update"
    RecArr[$ColA_Votes]="Update"
    RecArr[$ColQ_Votes]="Update"
    RecArr[$ColTitle]="Update"
    # --text="Set fields and click OK to update" 
    # Note a space after \ generates invalid command error from yad
    NewRecArr=('yad --form --width=900 --height=400 --center --skip-taskbar \
        --title="Select a file name and link it to Stack Exchange" \
        --text="Click OK to save. Click Cancel or press Escape to discard changes." \
        --field="File date":RO  --field="File name":FL  --field="Status":RO \
        --field="Answer +":RO   --field="Stack Exchange Address":TXT \
        --field="Question +":RO --field="Question Title":RO \
        ${RecArr[$ColFileDate]} ${RecArr[$ColFileName]} ${RecArr[$ColStatus]} \
        ${RecArr[$ColA_Votes]}  ${RecArr[$ColWebAddr]} \
        ${RecArr[$ColQ_Votes]}  ${RecArr[$ColTitle]}')
    ret=$?

    # Cancel =252, OK = 0
    # OK & Insert operation?
    if [[ $ret == 0 ]] && [[ $Action == $ButnInsert ]]; then
        # Create new list entry and renumber
        ((TransCount++)) # Update number of changes
        let i=1      # Base 0 array, record number is second field

        while [ $i -lt $ListArrCnt ] ; do
            if [ ${ListArr[$i]} -eq ${RecArr[$ColRecNo]} ]; then
                # We have matching record number to insert before
                NewArr+=( false )               # Selected
                NewArr+=( "${RecArr[$ColRecNo]}" ) # Will be renumbered
                NewArr+=( "${NewRecArr[$NewFileDate]}" )
                NewArr+=( "${NewRecArr[$NewFileName]}" )
                NewArr+=( "${NewRecArr[$NewStatus]}" )
                NewArr+=( "${NewRecArr[$NewA_Votes]}" )
                NewArr+=( "${NewRecArr[$NewWebAddr]}" )
                NewArr+=( "${NewRecArr[$NewQ_Votes]}" )
                NewArr+=( "${NewRecArr[$NewTitle]}" )
            fi
            let j=$(( $i-1 ))
            let k=$(( $j+$RecArrCnt ))
            while [ $j -lt $k ] ; do
                NewArr+=( "${ListArr[$j]}" )
                j=$(($j + 1))
            done
            let i=$(($i + $RecArrCnt)) # Next list array entry to copy
        done
        ListArr=("${NewArr[@]}")
        unset NewArr
        RenumberListArr

    # OK & Edit operation?
    elif [[ $ret == 0 ]] && [[ $Action == $ButnEdit ]]; then
        # Update array entry
        ((TransCount++))
        let i=1
        while [ $i -lt $ListArrCnt ] ; do
            if [ ${ListArr[$i]} -eq ${RecArr[1]} ]; then
                # We have matching record number
                ListArr[++i]="${NewRecArr[$NewFileDate]}"
                ListArr[++i]="${NewRecArr[$NewFileName]}"
                ListArr[++i]="${NewRecArr[$NewStatus]}"
                ListArr[++i]="${NewRecArr[$NewA_Votes]}"
                ListArr[++i]="${NewRecArr[$NewWebAddr]}"
                ListArr[++i]="${NewRecArr[$NewQ_Votes]}"
                ListArr[++i]="${NewRecArr[$NewTitle]}"
                let i=$(($ListArrCnt + 1)) # force exit from while loop
            else
                let i=$(($i + $RecArrCnt)) # Check next entry
            fi
        done
    else
        : # noop for readibility: Cancel or Escape pressed in Insert / Edit window
    fi

# View or Delete record?
elif [[ $Action == $ButnView ]] || [[ $Action == $ButnDelete ]] ; then

    # Note if there is a space after "\", the next line generates
    # "invalid command" error message from yad.
    if [[ $Action == $ButnDelete ]] ; then
        YadTitle="Do you really want to delete this entry?"
        YadText="Click OK to confirm delete."
    else
        YadTitle="websync - Single entry view mode"
        YadText="Click any button or press Escape after viewing entry."
    fi

    yad --width=900 --height=600 --form --center --skip-taskbar \
        --title="$YadTitle"      --text="$YadText" \
        --field="File date":RO   --field="File name":TXT --field="Status":RO \
        --field="Answer +":RO    --field="Stack Exchange Address":TXT \
        --field="Question +":RO  --field="Question Title":TXT \
        ${RecArr[$ColFileDate]} ${RecArr[$ColFileName]} ${RecArr[$ColStatus]} \
        ${RecArr[$ColA_Votes]}  ${RecArr[$ColWebAddr]}  ${RecArr[$ColQ_Votes]} \
        ${RecArr[$ColTitle]}
    ret=$?

    if [[ $Action == $ButnView ]] ; then
        continue
    fi

    # Cancel =252, OK = 0
    if [[ $ret == 0 ]] && [[ $Action == $ButnDelete ]] ; then
        # Delete record from list array and renumber
        ((TransCount++))
        let i=1
        while [ $i -lt $ListArrCnt ] ; do
            if [ ${ListArr[$i]} -eq ${RecArr[$ColRecNo]} ]; then
                # We have matching record number to delete
                j=$(($i - 1))
                k=$(($j + $RecArrCnt))
                while [ $j -lt $k ] ; do
                    unset 'ListArr[$j]'
                    j=$(($j + 1))
                done
                for i in "${!ListArr[@]}"; do
                    NewArr+=( "${ListArr[$i]}" )
                done
                ListArr=("${NewArr[@]}")
                unset NewArr
                let i=$(($ListArrCnt + 1)) # force exit from while loop
            else
                let i=$(($i + $RecArrCnt)) # Check next entry
            fi
        done
        RenumberListArr
    else
        : # cancel delete operation.
    fi

# Run update process?
elif [[ $Action == $ButnUpdate ]] ; then
    time UpdateAllOrOne
    ret=$?

# Cancel all changes or "252"= X the window or Escape?
elif [[ $Action == $ButnCancel ]] || [[ $Action == 252 ]] ; then
    if [[ $TransCount -gt 0 ]] ; then
        ('yad --image "dialog-question" --title "websync - Exit confirmation." \
        --text="You have made $TransCount change(s). Do you really want to exit?" \
        --button=_Stay:1 --button=_Exit:2 --center')

        if [[ $? -eq 2 ]] ; then
            exit
        fi
    else
        exit
    fi

# Save changes?
elif [[ $Action == $ButnSave ]] ; then
    # Save
    echo "${ListArr[*]}" > ~/.websync # Using * instead of @ preserves |
    ExternalSortArray
    exit
else
    yad --error --center --text "websync - Unknown button return code: $Action"
    exit
fi

done

IFS="$OldIFS"

exit

spawn-progress-multi script

Si vous ne mettez pas le fichier spawn-progress-multi dans votre chemin, websync ne pourra pas l'exécuter

#!/bin/bash

# NAME: spawn-progress-multi

Percent=0

MYNAME=%pre%
/usr/bin/logger $MYNAME "multi-progress FIFO named pipe: "
val=""
/usr/bin/logger $MYNAME "multi-progress yad parameters: "
/usr/bin/logger $MYNAME "multi-progress bar number to watch: "

while true ; do # loop until 100 %

    # Percent=$(cat "")
    [[ -f "" ]] && read -r Percent < ""
    echo "$Percent"
    if [[ $Percent == *":100"* ]] ; then break ; fi ;

done | yad 

exit 0
    
réponse donnée WinEunuuchs2Unix 06.04.2017 - 01:40
la source
1

Introduction

Cette solution est divisée en plusieurs réponses en raison de la limitation de taille de 32 Ko pour les réponses à Ask Ubuntu (AU).

Cette première section fournit le guide de l’utilisateur avec des captures d’écran et des explications sur le terrain.

La section suivante fournit les scripts bash qui accomplissent le travail.

Aperçu

Toutes les réponses à Ask Ubuntu (AU) sont stockées au format HTML (Hypertext Markup Language). Il y a un haut degré de confiance que cette application fonctionnera sur tous les sites Stack Exchange (SE), mais elle n'a été testée qu'avec AU.

L’application va:

  • Extraire le titre de la question
  • Extraire les commentaires de la question
  • Extraire les commentaires des réponses
  • Extraire le code SE correspondant aux trois premières lignes du nom de fichier lié contenant le code
  • Exécutez la commande diff entre le code SE et le code local affichant les résultats dans gedit .
  • Afficher les barres de progression
  • Interface utilisateur facile à utiliser sans configuration de terminal
  • Aucune installation autre que la copie du script bash
  • Livré avec des exemples de données sur des fichiers existants sur disque (Ubuntu 16.04) et des réponses existantes.

Exemple de fenêtre principale

Cet écran de démonstration devait être rapide et le cadre réduit pour tenir dans une limite de fichier de 2 Mo. Il montre les données par défaut créées lors de la première exécution du script. Voici ce qui se passe:

  • Sélectionnez la deuxième entrée
  • Cliquez sur le bouton Update
  • wget télécharge la question et répond depuis Stack Exchange une barre de progression est brièvement affichée.
  • La question et la réponse sont analysées et une barre de progression s’affiche pendant environ 3 secondes.
  • La commande diff a comparé le code local ~/.bashrc à la réponse sur Stack Exchange et gedit a été utilisé pour afficher les différences.

Voici ce qui a été manqué après la fin de l’animation:

gedit est utilisé pour afficher les différences entre votre code local ~/.bashrc et la réponse d'échange de la pile.

Après avoir fermé gedit , l’écran principal réapparaît et maintenant les champs "Question en haut", "Réponse en haut" et "Titre en question" sont remplis.

Exploration en cliquant sur le bouton View

Ici, vous pouvez voir tous les champs d’une entrée qui ne correspond pas à l’écran principal. Vous pouvez copier sur le clipbaord l'adresse du site Web d'échange de pile que vous pouvez ensuite coller dans votre navigateur. Vous pouvez voir la date de dernière modification du fichier de code stocké sur votre système.

Le champ État peut contenir:

  • Update - Une nouvelle entrée a été ajoutée ou une entrée existante a été modifiée. Cliquez sur le bouton Mettre à jour pour effacer tous les champs marqués comme mise à jour et définir avec les valeurs réelles de Stack Exchange.
  • Bad file - Le nom de fichier spécifié n'existe plus.
  • Empty file - Le nom de fichier spécifié contient zéro octet.
  • 3 lines not found - Les trois premières lignes du fichier spécifié (les lignes vides sont ignorées) n'ont pas été trouvées dans la réponse Stack Exchange. Le mauvais nom de fichier a été entré ou la réponse Stack Exchange incorrecte a été fournie ou les fichiers ont été modifiés de sorte que les trois premières lignes ne correspondent plus.
  • Bad Answer - L'adresse du site n'existe pas.
  • Answer < 1K - L'adresse du site Web existe mais la réponse est inférieure à 1 Ko.
  • Different - Le fichier de code local et la réponse Stack Exchange ont des différences.
  • Matches - Le fichier de code local correspond à la réponse à la réponse Stack Exchange.
  • Diff parameter Error - Les paramètres utilisés pour appeler la commande diff contiennent une ou plusieurs erreurs. Utilisez man diff pour examiner les options valides.

Portée du projet

L’objectif principal est de déterminer quelles réponses ont été modifiées par d’autres utilisateurs et de les convertir en fichiers de code locaux. L'autre objectif est de déterminer quelles réponses dans Stack Exchange doivent être mises à jour après que le changement de codage s'est produit localement. Enfin, les réponses «chaudes» peuvent être suivies avec les résultats des votes de réponse.

Aucune base de données SQL ne doit être utilisée. Seuls les fichiers out-of-the-box-bash doivent être utilisés. L'application doit utiliser yad comme interface utilisateur graphique. Zenity est trop limité car il ne peut pas afficher les valeurs d'origine dans les formulaires, ne peut pas masquer les colonnes lorsque la base de données est trop large et ne permet pas l'ajout de boutons pour contrôler le flux du programme.

Expliquant la fenêtre principale ci-dessus, elle affiche des entrées défilables contenant:

  • Bouton radio pour sélectionner une entrée
  • Le nom du fichier local contenant le code
  • Répondre à vos votes (que votre code posté et votre réponse écrite sont en train d’obtenir)
  • Question Up-Votes (pour montrer l’intérêt mondial de cette question SE)
  • Titre de la question

Un résumé des boutons de la fenêtre principale est:

  • View - affiche l'entrée sélectionnée.
  • Insert before - insère une nouvelle entrée avant l'entrée sélectionnée.
  • Edit - modifie l'entrée sélectionnée.
  • Delete - supprime l'entrée de sélection (une confirmation est requise).
  • Update - téléchargez la réponse de Stack Exchange et analysez-la.
  • Cancel ALL - Annule toutes les modifications (confirmation requise si des modifications ont été apportées). La touche Échap ou X sur la fenêtre a le même effet.
  • Save - Enregistre les modifications sur le disque.

Les boutons View et Delete apparaissent dans la même fenêtre que ci-dessus.

Les boutons Insert before et Edit apparaissent dans une fenêtre similaire, mais certains champs ne sont pas entrés et sont initialisés avec “Update”. Cela indique que le bouton Update de la fenêtre principale doit être cliqué pour récupérer les données de Stack Exchange ultérieurement. Les champs non saisis sont les suivants: date du fichier, statut, votes de réponse, votes de questions et titre.

Mises à jour de juin 2017

Le code a été révisé pour trier les entrées de tableau en fonction du titre de la question + du nom du fichier local lorsque les modifications sont enregistrées. Il n'est plus nécessaire d'insérer manuellement des enregistrements dans un ordre séquentiel.

Vous pouvez maintenant update all en cliquant sur le bouton update sans sélectionner d'enregistrements spécifiques. Lors de la mise à jour de toutes les comparaisons de fichiers, elles sont regroupées dans un seul fichier et présentées par gedit une fois l'opération terminée. Les réponses avec un code source identique ne sont pas présentées dans les boîtes de dialogue interrompant le flux mais placées comme lignes d'état dans le fichier diff .

Les touches d’accélération sont fournies pour les boutons. Maintenez la touche Alt enfoncée, puis appuyez sur la première lettre du bouton que vous souhaitez sélectionner.

sed prenait 3 secondes pour changer le HTML en texte, ce qui était trop long. Il a été remplacé par construit dans bash search & amp; remplacer et le temps est maintenant une seconde ou moins.

Malheureusement, ces changements de code sont 2 000 caractères trop longs pour la publication de Ask Ubuntu , veuillez donc laisser un commentaire si vous souhaitez une copie du code et trouver un endroit pour le publier.

    
réponse donnée WinEunuuchs2Unix 06.04.2017 - 00:41
la source

Lire d'autres questions sur les étiquettes