Skip to content

Instantly share code, notes, and snippets.

@stephan-t
Last active July 4, 2020 22:49
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save stephan-t/561d0e473dddb270be3da6a8ca994306 to your computer and use it in GitHub Desktop.
Save stephan-t/561d0e473dddb270be3da6a8ca994306 to your computer and use it in GitHub Desktop.
Fixes texture corruption in VS Code terminal after resuming from suspend
#!/bin/bash
# Fixes texture corruption in VS Code terminal after resuming from suspend.
#
# Place script in /lib/systemd/system-sleep/ so it can run after resuming.
#
# Dependencies: jq
case "$1" in
post)
# Check if VS Code is running
if [ -z "$(pgrep -x code)" ]; then
exit 0
fi
user=$(cut -d " " -f 1 <<< $(users))
settings_file="/home/$user/.config/Code/User/settings.json"
# Check if settings file is a symlink
if [ -L "$settings_file" ]; then
settings_link=$settings_file
settings_file=$(readlink $settings_file)
fi
# Create backup of settings
backup_file="/home/$user/.config/Code/User/settings.json.bak"
if [ ! -e "$backup_file" ]; then
cp $settings_file $backup_file
fi
# Before overwriting, ensure settings file is not truncated from errors
tmp_file='/tmp/settings.json'
overwrite() {
local tmp_file_lines=$(wc -l $tmp_file | cut -d " " -f 1)
if [ "$tmp_file_lines" -le 1 ]; then
rm $tmp_file
exit 1
else
chown $user:$user $tmp_file
mv $tmp_file $settings_file
if [ ! -z ${settings_link+x} ]; then
touch -h $settings_link
fi
fi
}
# Wait for screen unlock
tail -f /var/log/auth.log -n 1 | sed '/unlocked login keyring/ q;/Power key pressed/ q'
# Get current zoom level
zoom_level=$(jq '.["window.zoomLevel"]' $settings_file)
# Add missing key if required
if [ "$zoom_level" = "null" ]; then
jq '. + { "window.zoomLevel": 0 }' $settings_file > $tmp_file
overwrite
fi
# Change zoom level
let zoom_level++
jq '.["window.zoomLevel"] = $zoom' --argjson zoom $zoom_level \
$settings_file > $tmp_file
overwrite
sleep 0.5
let zoom_level--
jq '.["window.zoomLevel"] = $zoom' --argjson zoom $zoom_level \
$settings_file > $tmp_file
overwrite
;;
esac
@Fmstrat
Copy link

Fmstrat commented Jun 23, 2020

Couldn't you just check for zoom then sed -i? That would also allow this to work with dotfiles. As it stands of settings.json is a symlink, this kills the link.

See: https://gist.github.com/Fmstrat/7de01996206537b9dbc8f673b2c5ced2

@stephan-t
Copy link
Author

Couldn't you just check for zoom then sed -i? That would also allow this to work with dotfiles. As it stands of settings.json is a symlink, this kills the link.

See: https://gist.github.com/Fmstrat/7de01996206537b9dbc8f673b2c5ced2

Hi @Fmstrat, thanks for your suggestion and contribution.

I initially thought about using sed but found that it is advised against for parsing complex structured data such as JSON or XML since there are a lot of chances for it to go wrong, especially if the data is malformed. It is usually recommended to use dedicated parsing tools such as jq to ensure reliability.

Reference: https://askubuntu.com/questions/863865/regex-with-sed-command-to-parse-json-text

@Fmstrat
Copy link

Fmstrat commented Jun 23, 2020

That makes sense. In that case, I would recommend outputting into the file directly, such as with > settings.json as to handle any symlinks/dotfiles (vs moving over it).

Also, it looks like you could simplify your wait on unlock with this: https://gist.github.com/Fmstrat/7de01996206537b9dbc8f673b2c5ced2#file-vscode-texture-fix-sh-L21

Lastly, how do you get the $(users) variable? The script fails for me because that variable doesn't exist (Ubuntu 20.04, logged into a domain). Did it work for you out of the box? Maybe it's a domain thing.

@stephan-t
Copy link
Author

Thanks @Fmstrat. I simplified the "wait on unlock" with your code.

The reason why I don't direct jq's output to settings.json is because if there is any error in jq's input or filter string then it will output an empty file, which is why the script first outputs to a temporary file and verifies it in the overwrite function before overwriting settings.json. However, I have now modified the code to check for symlinks and handle it appropriately.

I used the built-in users command (Ubuntu 20.04) to get the list of currently logged in users, which then uses the first username in the list as a variable for the rest of the script. It works out of the box for me. Unfortunately, I am not familiar with domain logins in Ubuntu so I wouldn't know how to modify the code to work with that. I only used the users command so that others using the script wouldn't have to modify anything to get it to work but you can always hard code your username into the user variable. You can also try the who command to see if it lists your domain username. Using whoami command won't work because the script will execute as root on resume.

@Fmstrat
Copy link

Fmstrat commented Jul 3, 2020

@stephan-t I've noticed one other thing that I've corrected in my version of the script. Users who assign their power button to pm-hibernate never have to "re-login", and thus nothing shows up in the Auth log. So the tail command just runs forever. The fix is this line in my version if it helps: https://gist.github.com/Fmstrat/7de01996206537b9dbc8f673b2c5ced2#file-vscode-texture-fix-sh-L20

@stephan-t
Copy link
Author

Good catch @Fmstrat, thank you. I've updated my script to include that as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment