diff options
Diffstat (limited to 'configs/shared')
71 files changed, 2875 insertions, 503 deletions
diff --git a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-keybindings.el b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-keybindings.el index 8d6fe0530f46..6272b1127088 100644 --- a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-keybindings.el +++ b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-keybindings.el @@ -71,6 +71,7 @@ "el" (lambda () (interactive) (wpc/find-file-split "~/variables.zsh")) "ex" (lambda () (interactive) (wpc/find-file-split "~/.Xresources")) "ei" (lambda () (interactive) (wpc/find-file-split "~/.config/i3/config")) + "em" (lambda () (interactive) (wpc/find-file-split "~/.tmux.conf")) "B" #'magit-blame "w" #'save-buffer diff --git a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-misc.el b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-misc.el index 46812c60d652..5e513cd6f0ee 100644 --- a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-misc.el +++ b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-misc.el @@ -45,10 +45,10 @@ ;; create file bookmarks (set-register ?e '(file . "~/.emacs.d/wpc/packages")) (set-register ?n '(file . "~/programming/nixify/configuration.nix")) -(set-register ?d '(file . "~/programming/dotfiles")) +(set-register ?d '(file . "~/Dropbox/dotfiles")) (set-register ?s '(file . "~/.slate.js")) (set-register ?D '(file . "~/Dropbox")) -(set-register ?o '(file . "~/Documents/org/")) +(set-register ?o '(file . "~/Dropbox/org/")) ;; TODO: change this to `(getenv "ORG_DIRECTORY")' (set-register ?v '(file . "~/.config/nvim/init.vim")) (set-register ?e '(file . "~/.emacs.d/init.el")) @@ -58,6 +58,7 @@ (set-register ?l '(file . "~/variables.zsh")) (set-register ?x '(file . "~/.Xresources")) (set-register ?i '(file . "~/.config/i3/config")) +(set-register ?m '(file . "~/.tmux.conf")) (set-register ?p `(file . ,wpc/current-project)) diff --git a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-org.el b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-org.el index dcbe06688519..06e2a27bf948 100644 --- a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-org.el +++ b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-org.el @@ -6,29 +6,39 @@ ;;; Code: +(getenv "ORG_DIRECTORY") + ;; TODO: figure out how to nest this in (use-package org ...) (setq org-capture-templates - (quote ( + `( + + ("w" "work" entry (file+headline + ,(f-join (getenv "ORG_DIRECTORY") "work.org") + "Tasks") + "* TODO %?") -("w" "work" entry (file+headline "~/Documents/org/work.org" "Tasks") - "* TODO %?") + ("p" "personal" entry (file+headline + ,(f-join (getenv "ORG_DIRECTORY") "personal.org") + "Tasks") + "* TODO %? ") -("p" "personal" entry (file+headline "~/Documents/org/personal.org" "Tasks") - "* TODO %? ") + ("i" "ideas" entry (file+headline + ,(f-join (getenv "ORG_DIRECTORY") "ideas.org") + "Tasks") + "* %? ") -))) + )) (evil-set-initial-state 'org-mode 'insert) (use-package org - :preface - (defconst wpc-org-directory - "~/Documents/org") :config ; (general-add-hook org-mode-hook (disable linum-mode)) (general-define-key :prefix "C-c" "l" #'org-store-link "a" #'org-agenda "c" #'org-capture) + (setq org-todo-keywords + '((sequence "TODO" "BLOCKED" "DONE"))) (setq org-default-notes-file (wpc/org-file "notes")) (setq org-log-done 'time) (setq org-agenda-files (list (wpc/org-file "work") diff --git a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-ui.el b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-ui.el index 6fd34516bfd1..2334a8947ea3 100644 --- a/configs/shared/emacs/.emacs.d/wpc/packages/wpc-ui.el +++ b/configs/shared/emacs/.emacs.d/wpc/packages/wpc-ui.el @@ -10,7 +10,7 @@ (setq-default line-spacing 4) ;; change font -(add-to-list 'default-frame-alist '(font . "Source Code Pro-9")) +(add-to-list 'default-frame-alist '(font . "Operator Mono Book-9")) (defconst wpc/font-size-step 10 "The amount (%) by which to increase or decrease a font.") diff --git a/configs/shared/gpg/.gnupg/import.sh b/configs/shared/gpg/.gnupg/import.sh index 9fb9be64f060..e698aa3d2bd2 100644 --- a/configs/shared/gpg/.gnupg/import.sh +++ b/configs/shared/gpg/.gnupg/import.sh @@ -3,7 +3,7 @@ set -e # Run this script to import all of the information exported by `export.sh`. -# Usage: ./export.sh path/to/directory +# Usage: ./import.sh path/to/directory gpg --import "$1/public.asc" gpg --import "$1/secret.asc" diff --git a/configs/shared/misc/.config/i3/config b/configs/shared/misc/.config/i3/config new file mode 100644 index 000000000000..d020ace806a4 --- /dev/null +++ b/configs/shared/misc/.config/i3/config @@ -0,0 +1,248 @@ +set $mod Mod1 +set $super Mod4 + +# Keymapping philosophy: +# When I feel it's appropriate, I try to borrow existing KBDs from OSX or +# Windows. For example, I use Ctrl+Alt+Del to start the screen lock, since this +# is a really well-known KBD. One notable difference is that when I'm borrowing +# OSX KBDs, I prefer using Alt instead of Super since the keyboard that I'm +# using has the Alt key in the same location as the Super key on my mac +# keyboard. I could rebind this, and I just may. But for now, that's worth +# pointing out. +# The reason behind borrowing from Windows and OSX is that some of these +# keybindings are hardwired into my muscle memory. I also tend to work between +# Linux and OSX quite often. Since OSX is much more difficult to remap KBDs +# than it is in Linux, I prefer to support the OSX KBDs to reduce the number of +# KBDs my feeble memory needs to store. + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +font pango:monospace 8 + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# gaps +# gaps inner 20 +# gaps outer 0 +# smart_gaps on + +# KBD Principles: +# $mod+Ctrl+<app_char> = starting an application vertically +# $mod+Ctrl+Shift+<app_char> = starting an application horizontally +# where <app_char> is a reserved character for a commonly used application. +# +# <app_char> definitions: +# terminal = t, Return +# emacs = e +# chrome = c +# spotify = s +# +# Vertical +bindsym $mod+Ctrl+t split v; exec st +bindsym $mod+Ctrl+Return split v; exec st +bindsym $mod+Ctrl+e split v; exec emacs +bindsym $mod+Ctrl+c split v; exec google-chrome +bindsym $mod+Ctrl+s split v; exec spotify +# Horizontal +bindsym $mod+Ctrl+Shift+t split h; exec st +bindsym $mod+Ctrl+Shift+Return split h; exec st +bindsym $mod+Ctrl+Shift+e split h; exec emacs +bindsym $mod+Ctrl+Shift+c split h; exec google-chrome +bindsym $mod+Ctrl+Shift+s split h; exec spotify + +# audio controls +bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% # MBP Volume Up +bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% # MBP Volume Down +bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle # MBP Mute +bindsym F12 exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% # same Fn keys as MBP +bindsym F11 exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% # same Fn keys as MBP +bindsym F10 exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle # same Fn keys as MBP + +# pass integration +bindsym $mod+Ctrl+backslash exec ~/.config/i3/passmenu # mirroring the 1password KBD + +# screen brightness controls +bindsym XF86MonBrightnessUp exec light -A 10 +bindsym XF86MonBrightnessDown exec light -U 10 + +# integrate with Emacs's org-mode +bindsym $mod+o exec zsh -i -c org_capture +for_window [class="GoogleEmacs" instance="org-protocol-capture"] floating enable + +# ensure Spotify windows float +for_window [class="Spotify"] floating enable + +# ensure wallpaper +exec --no-startup-id feh --bg-scale ~/.local/share/wallpaper/cartoon-outdoors.jpg + +# ensure system service that run through XDG start +exec dex -ae i3 + +# dmenu configuration +bindsym $mod+space exec --no-startup-id dmenu_run +bindsym $mod+t exec --no-startup-id ~/.config/i3/dmenu_timer.sh ~/.local/share/sounds/gong.mp3 + +# file manager +bindsym $mod+x exec st -e ~/bin/lf # TODO: reconsider hardlink and expose ZSH's PATH to i3 + +# music player kbds +bindsym F9 exec --no-startup-id playerctl next # same Fn keys as MBP +bindsym F8 exec --no-startup-id playerctl play-pause # same Fn keys as MBP +bindsym F7 exec --no-startup-id playerctl previous # same Fn keys as MBP + +# Screenshot +bindsym $mod+s exec zsh -i -c snipit +bindsym Ctrl+Print exec scrot ~/Pictures/screenshots/%b-%d-%Y_%T.png # Windows style +# TODO: debug +bindsym $mod+Print exec scrot --focused ~/Pictures/screenshots/%b-%d-%Y_%T.png # Windows style +bindsym $mod+Shift+3 exec scrot ~/Pictures/screenshots/%b-%d-%Y_%T.png # OSX style +# TODO: debug +bindsym $mod+Shift+4 exec scrot --select ~/Pictures/screenshots/%b-%d-%Y_%T.png # OSX style +# Integration with Google's screenshot hosting server + +# online documentation +bindsym $mod+Shift+slash exec google-chrome https://i3wm.org/docs/userguide.html + +# no title bars +for_window [class="^.*"] border pixel 2 + +# disable mouse hover focus +focus_follows_mouse no + +# kill focused window +bindsym $mod+q kill + +# GTK Themes +exec --no-startup-id gnome-settings-daemon + +# wireless selection mechanism +exec --no-startup-id nm-applet + +# lock the screen (Window's famous Ctrl-Alt-Delete) +bindsym $mod+Ctrl+Delete exec "/usr/share/goobuntu-desktop-files/xsecurelock.sh" +bindsym $mod+Shift+q exec "/usr/share/goobuntu-desktop-files/xsecurelock.sh" + +# sound applet +exec --no-startup-id gnome-sound-applet + +# change focus +bindsym $mod+h focus left +bindsym $mod+j focus down +bindsym $mod+k focus up +bindsym $mod+l focus right + +# move focused window +bindsym $mod+Shift+h move left 100 +bindsym $mod+Shift+j move down 100 +bindsym $mod+Shift+k move up 100 +bindsym $mod+Shift+l move right 100 + +# enable duplicating the current window vertically or horizontally +# bindsym $mod+- split v exec terminator +# bindsym $mod+\ split h exec terminator + +# enter fullscreen mode for the focused container +bindsym $mod+z fullscreen toggle + +# change container layout (stacked, tabbed, toggle split) +bindsym $super+e layout toggle split +bindsym $super+s layout stacking +bindsym $super+t layout tabbed + +# toggle tiling / floating +bindsym $mod+Shift+f floating toggle + +# toggle stickiness +bindsym $mod+Shift+s sticky toggle + +# change focus between tiling / floating windows +bindsym $mod+f focus mode_toggle + +# focus the parent container +bindsym $mod+a focus parent + +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" +set $ws5 "5" +set $ws6 "6" +set $ws7 "7" +set $ws8 "8" +set $ws9 "9" +set $ws10 "10" + +# jump to workspace +bindsym $mod+1 workspace $ws1 +bindsym $mod+2 workspace $ws2 +bindsym $mod+3 workspace $ws3 +bindsym $mod+4 workspace $ws4 +bindsym $mod+5 workspace $ws5 +bindsym $mod+6 workspace $ws6 +bindsym $mod+7 workspace $ws7 +bindsym $mod+8 workspace $ws8 +bindsym $mod+9 workspace $ws9 +bindsym $mod+0 workspace $ws10 + +# move and follow focused container to workspace +bindsym $mod+Shift+1 move container to workspace $ws1; workspace $ws1 +bindsym $mod+Shift+2 move container to workspace $ws2; workspace $ws2 +# bindsym $mod+Shift+3 move container to workspace $ws3; workspace $ws3 # commented out to support screenshot KBD +# bindsym $mod+Shift+4 move container to workspace $ws4; workspace $ws4 # commented out to support screenshot KBD +bindsym $mod+Shift+5 move container to workspace $ws5; workspace $ws5 +bindsym $mod+Shift+6 move container to workspace $ws6; workspace $ws6 +bindsym $mod+Shift+7 move container to workspace $ws7; workspace $ws7 +bindsym $mod+Shift+8 move container to workspace $ws8; workspace $ws8 +bindsym $mod+Shift+9 move container to workspace $ws9; workspace $ws9 +bindsym $mod+Shift+0 move container to workspace $ws10; workspace $ws10 + +# move focused container to workspace +bindsym $mod+Ctrl+1 move container to workspace $ws1 +bindsym $mod+Ctrl+2 move container to workspace $ws2 +bindsym $mod+Ctrl+3 move container to workspace $ws3 +bindsym $mod+Ctrl+4 move container to workspace $ws4 +bindsym $mod+Ctrl+5 move container to workspace $ws5 +bindsym $mod+Ctrl+6 move container to workspace $ws6 +bindsym $mod+Ctrl+7 move container to workspace $ws7 +bindsym $mod+Ctrl+8 move container to workspace $ws8 +bindsym $mod+Ctrl+9 move container to workspace $ws9 +bindsym $mod+Ctrl+0 move container to workspace $ws10 + +# reload, restart i3 +bindsym $super+r reload +bindsym $super+Shift+r restart + + +# resize window (you can also use the mouse for that) +mode "resize" { + bindsym h resize shrink width 10 px or 10 ppt + bindsym j resize shrink height 10 px or 10 ppt + bindsym k resize grow height 10 px or 10 ppt + bindsym l resize grow width 10 px or 10 ppt + bindsym Return mode "default" + bindsym Caps_Lock mode "default" + bindsym $mod+Shift+r mode "default" +} +bindsym $mod+Shift+r mode "resize" + +# passthrough mode to support Emacs, Tmux, Vim KBDs for window and pane management +mode "passthrough" { + bindsym $mod+Escape mode "default" +} +bindsym $mod+Escape mode "passthrough" + +# Colors +set $foreground #61afef +set $background #dfdfdf + +# window borders +# Format: border background text indicator child_border +client.focused $foreground $background $foreground $foreground $foreground + +bar { + status_command i3status + position top +} diff --git a/configs/shared/misc/.config/i3/dmenu_timer.sh b/configs/shared/misc/.config/i3/dmenu_timer.sh new file mode 100755 index 000000000000..9d62ead73091 --- /dev/null +++ b/configs/shared/misc/.config/i3/dmenu_timer.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +# Select common timer intervals with dmenu and play an alarm sound when +# finished. Useful if you bind a KBD in a window manager such as i3. Pass the +# path to the alarm mp3 as the only argument. +# +# Usage: ./dmenu_timer.sh path/to/alarm.mp3 + +times=$(cat <<EOF +1 minute +2 minutes +3 minutes +4 minutes +5 minutes +10 minutes +15 minutes +20 minutes +30 minutes +45 minutes +1 hour +2 hours +EOF +) +selection=$(echo "$times" | dmenu) + +case $selection in + '1 minute') + notify-send 'Timer' 'Set for 1 minute' && \ + sleep 1m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '2 minutes') + notify-send 'Timer' 'Set for 2 minute' && \ + sleep 2m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '3 minutes') + notify-send 'Timer' 'Set for 3 minutes' && \ + sleep 3m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '4 minutes') + notify-send 'Timer' 'Set for 4 minutes' && \ + sleep 4m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '5 minutes') + notify-send 'Timer' 'Set for 5 minutes' && \ + sleep 5m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '10 minutes') + notify-send 'Timer' 'Set for 10 minutes' && \ + sleep 10m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '15 minutes') + notify-send 'Timer' 'Set for 15 minutes' && \ + sleep 15m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '20 minutes') + notify-send 'Timer' 'Set for 20 minutes' && \ + sleep 20m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '30 minutes') + notify-send 'Timer' 'Set for 30 minutes' && \ + sleep 30m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '45 minutes') + notify-send 'Timer' 'Set for 45 minutes' && \ + sleep 45m && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '1 hour') + notify-send 'Timer' 'Set for 1 hour' && \ + sleep 1h && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + '2 hours') + notify-send 'Timer' 'Set for 2 hours' && \ + sleep 2h && \ + notify-send 'Timer' 'Finished.' && \ + mpg123 $1 && \ + exit 0 + ;; + *) + notify-send 'Timer' 'No supported time selected. Exiting...' && exit 1 +esac diff --git a/configs/shared/misc/.config/i3/passmenu b/configs/shared/misc/.config/i3/passmenu new file mode 100755 index 000000000000..71c4538fa61a --- /dev/null +++ b/configs/shared/misc/.config/i3/passmenu @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +shopt -s nullglob globstar + +typeit=0 +if [[ $1 == "--type" ]]; then + typeit=1 + shift +fi + +prefix=${PASSWORD_STORE_DIR-~/.password-store} +password_files=( "$prefix"/**/*.gpg ) +password_files=( "${password_files[@]#"$prefix"/}" ) +password_files=( "${password_files[@]%.gpg}" ) + +password=$(printf '%s\n' "${password_files[@]}" | dmenu "$@") + +[[ -n $password ]] || exit + +if [[ $typeit -eq 0 ]]; then + pass show -c "$password" 2>/dev/null +else + pass show "$password" | { IFS= read -r pass; printf %s "$pass"; } | + xdotool type --clearmodifiers --file - +fi \ No newline at end of file diff --git a/configs/shared/misc/.config/i3/workspace_1.json b/configs/shared/misc/.config/i3/workspace_1.json new file mode 100644 index 000000000000..b5d3f9d8c53f --- /dev/null +++ b/configs/shared/misc/.config/i3/workspace_1.json @@ -0,0 +1,76 @@ +// vim:ts=4:sw=4:et +{ + // splitv split container with 2 children + "border": "normal", + "floating": "auto_off", + "layout": "splitv", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "pixel", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 925, + "width": 1072, + "x": 0, + "y": 0 + }, + "name": "emacs@wpcarro.lon.corp.google.com", + "percent": 0.5, + "swallows": [ + { + "class": "^GoogleEmacs$", + "instance": "^emacs$", + "title": "^google-emacs$" + } + ], + "type": "con" + }, + { + "border": "pixel", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 484, + "width": 724, + "x": 0, + "y": 0 + }, + "name": "i3-save-tree", + "percent": 0.5, + "swallows": [ + { + "class": "^st\\-256color$", + "instance": "^st\\-256color$", + "title": "^st-term$" + } + ], + "type": "con" + } + ] +} + +{ + "border": "pixel", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 2125, + "width": 1914, + "x": 1923, + "y": 32 + }, + "name": "i3: Layout saving in i3 - Google Chrome", + "percent": 0.5, + "swallows": [ + { + "class": "^Google\\-chrome$", + "instance": "^google\\-chrome$", + "title": "Chrome", + "window_role": "^browser$" + } + ], + "type": "con" +} diff --git a/configs/shared/misc/.config/i3status/config b/configs/shared/misc/.config/i3status/config new file mode 100644 index 000000000000..9df0af323846 --- /dev/null +++ b/configs/shared/misc/.config/i3status/config @@ -0,0 +1,29 @@ +general { + markup = "pango" + separator = " " + colors = true +} + +order += "time" +order += "tztime est" +order += "tztime pst" +order += "disk /" + +disk "/" { + prefix_type = "decimal" + format = "%avail / %total" +} + +time { + format = "%H:%M - %D" +} + +tztime est { + format = "%H:%M EST" + timezone = "US/Eastern" +} + +tztime pst { + format = "%H:%M PST" + timezone = "US/Pacific" +} \ No newline at end of file diff --git a/configs/shared/misc/.config/lf/lfrc b/configs/shared/misc/.config/lf/lfrc new file mode 100644 index 000000000000..59b8e5d80676 --- /dev/null +++ b/configs/shared/misc/.config/lf/lfrc @@ -0,0 +1 @@ +map D delete \ No newline at end of file diff --git a/configs/shared/misc/.config/nvim/init.vim b/configs/shared/misc/.config/nvim/init.vim index 4da8a5537076..148341a2c2ef 100644 --- a/configs/shared/misc/.config/nvim/init.vim +++ b/configs/shared/misc/.config/nvim/init.vim @@ -375,9 +375,6 @@ let g:airline_theme = 'hybrid' let g:swoopHighlight = ["hi! link SwoopBufferLineHi Warning", "hi! link SwoopPatternHi Error"] -nnoremap <M-q> :q<CR> - - " Jump to buffers. nmap <F1> :1b<CR> nmap <F2> :2b<CR> @@ -525,6 +522,7 @@ nnoremap <silent> <M-h> :TmuxNavigateLeft<CR> nnoremap <silent> <M-j> :TmuxNavigateDown<CR> nnoremap <silent> <M-k> :TmuxNavigateUp<CR> nnoremap <silent> <M-l> :TmuxNavigateRight<CR> +nnoremap <silent> <M-q> :q<CR> " make Y do what is intuitive given: " D: deletes until EOL diff --git a/configs/shared/misc/.config/rofi/config b/configs/shared/misc/.config/rofi/config new file mode 100644 index 000000000000..3bc0a7cab04e --- /dev/null +++ b/configs/shared/misc/.config/rofi/config @@ -0,0 +1 @@ +rofi.theme: /usr/share/rofi/themes//lb.rasi diff --git a/configs/shared/misc/.config/terminator/config b/configs/shared/misc/.config/terminator/config new file mode 100644 index 000000000000..5e62b9d4be5c --- /dev/null +++ b/configs/shared/misc/.config/terminator/config @@ -0,0 +1,20 @@ +[global_config] +[keybindings] +[layouts] + [[default]] + [[[child1]]] + parent = window0 + type = Terminal + [[[window0]]] + parent = "" + type = Window +[plugins] +[profiles] + [[default]] + background_type = transparent + cursor_color = "#aaaaaa" + cursor_shape = ibeam + font = Source Code Pro 12 + scrollbar_position = hidden + show_titlebar = False + use_system_font = False diff --git a/configs/shared/misc/.irssi/config b/configs/shared/misc/.irssi/config new file mode 100644 index 000000000000..3d29350accd7 --- /dev/null +++ b/configs/shared/misc/.irssi/config @@ -0,0 +1,33 @@ +servers = ( + { + address = "chat.freenode.net"; + chatnet = "Freenode"; + port = "6697"; + use_tls = "yes"; + tls_verify = "yes"; + autoconnect = "yes"; + } +); + +chatnets = { + Freenode = { + type = "IRC"; + autosendcmd = "/msg nickserv identify wpcarro ]3Fwus]YF7yXPB6Re/Me"; + }; +}; + +channels = ( + { name = "#nixos"; chatnet = "Freenode"; autojoin = "Yes"; }, + { name = "#i3"; chatnet = "Freenode"; autojoin = "No"; }, + { name = "#pass"; chatnet = "Freenode"; autojoin = "No"; }, +); + +settings = { + core = { + real_name = "William Carroll's account"; + user_name = "wpcarro"; + nick = "wpcarro"; + }; + "fe-text" = { actlist_sort = "refnum"; }; + "fe-common/core" = { theme = "default"; }; +}; diff --git a/configs/shared/misc/.local/share/fonts/.uuid b/configs/shared/misc/.local/share/fonts/.uuid new file mode 100644 index 000000000000..d45a157377b4 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/.uuid @@ -0,0 +1 @@ +5c006ff1-cbf7-40ef-b117-5f8c46def8c9 \ No newline at end of file diff --git a/configs/shared/misc/.local/share/fonts/FiraMono-Bold.ttf b/configs/shared/misc/.local/share/fonts/FiraMono-Bold.ttf new file mode 100644 index 000000000000..12f05a77e551 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/FiraMono-Bold.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/FiraMono-Medium.ttf b/configs/shared/misc/.local/share/fonts/FiraMono-Medium.ttf new file mode 100644 index 000000000000..a80896cf49dc --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/FiraMono-Medium.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/FiraMono-Regular.ttf b/configs/shared/misc/.local/share/fonts/FiraMono-Regular.ttf new file mode 100644 index 000000000000..f0572e14c3dc --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/FiraMono-Regular.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hack-Bold.ttf b/configs/shared/misc/.local/share/fonts/Hack-Bold.ttf new file mode 100644 index 000000000000..7ff4975285da --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hack-Bold.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hack-BoldItalic.ttf b/configs/shared/misc/.local/share/fonts/Hack-BoldItalic.ttf new file mode 100644 index 000000000000..3b137d9715e4 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hack-BoldItalic.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hack-Italic.ttf b/configs/shared/misc/.local/share/fonts/Hack-Italic.ttf new file mode 100644 index 000000000000..d26198a321a5 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hack-Italic.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hack-Regular.ttf b/configs/shared/misc/.local/share/fonts/Hack-Regular.ttf new file mode 100644 index 000000000000..92a90cb06e05 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hack-Regular.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-Black.otf b/configs/shared/misc/.local/share/fonts/Hasklig-Black.otf new file mode 100644 index 000000000000..a276f67210d5 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-Black.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-BlackIt.otf b/configs/shared/misc/.local/share/fonts/Hasklig-BlackIt.otf new file mode 100644 index 000000000000..d5981c124411 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-BlackIt.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-Bold.otf b/configs/shared/misc/.local/share/fonts/Hasklig-Bold.otf new file mode 100644 index 000000000000..95356b671c09 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-Bold.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-BoldIt.otf b/configs/shared/misc/.local/share/fonts/Hasklig-BoldIt.otf new file mode 100644 index 000000000000..f7bff9a4c959 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-BoldIt.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-ExtraLight.otf b/configs/shared/misc/.local/share/fonts/Hasklig-ExtraLight.otf new file mode 100644 index 000000000000..510a03936cd2 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-ExtraLight.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-ExtraLightIt.otf b/configs/shared/misc/.local/share/fonts/Hasklig-ExtraLightIt.otf new file mode 100644 index 000000000000..5c903455bdf2 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-ExtraLightIt.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-It.otf b/configs/shared/misc/.local/share/fonts/Hasklig-It.otf new file mode 100644 index 000000000000..dd645861a4e8 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-It.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-Light.otf b/configs/shared/misc/.local/share/fonts/Hasklig-Light.otf new file mode 100644 index 000000000000..84f3f58a45a3 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-Light.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-LightIt.otf b/configs/shared/misc/.local/share/fonts/Hasklig-LightIt.otf new file mode 100644 index 000000000000..70d02635ce89 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-LightIt.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-Medium.otf b/configs/shared/misc/.local/share/fonts/Hasklig-Medium.otf new file mode 100644 index 000000000000..c89beb39f5eb --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-Medium.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-MediumIt.otf b/configs/shared/misc/.local/share/fonts/Hasklig-MediumIt.otf new file mode 100644 index 000000000000..197c78907b80 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-MediumIt.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-Regular.otf b/configs/shared/misc/.local/share/fonts/Hasklig-Regular.otf new file mode 100644 index 000000000000..913fb8c080f6 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-Regular.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-Semibold.otf b/configs/shared/misc/.local/share/fonts/Hasklig-Semibold.otf new file mode 100644 index 000000000000..2b4f008918d4 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-Semibold.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/Hasklig-SemiboldIt.otf b/configs/shared/misc/.local/share/fonts/Hasklig-SemiboldIt.otf new file mode 100644 index 000000000000..e2d9d7a48fb4 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/Hasklig-SemiboldIt.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-Bold.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-Bold.otf new file mode 100644 index 000000000000..01d93a707116 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-Bold.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-BoldItalic.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-BoldItalic.otf new file mode 100644 index 000000000000..f912e44c87d9 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-BoldItalic.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-Book.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-Book.otf new file mode 100644 index 000000000000..a636ec0c61b8 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-Book.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-BookItalic.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-BookItalic.otf new file mode 100644 index 000000000000..a05c10f446c9 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-BookItalic.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-Light.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-Light.otf new file mode 100644 index 000000000000..b199504c0ffa --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-Light.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-LightItalic.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-LightItalic.otf new file mode 100644 index 000000000000..befd0390c901 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-LightItalic.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-Medium.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-Medium.otf new file mode 100644 index 000000000000..6d1cc1542a21 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-Medium.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-MediumItalic.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-MediumItalic.otf new file mode 100644 index 000000000000..af9442caa35a --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-MediumItalic.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-XLight.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-XLight.otf new file mode 100644 index 000000000000..813a64247da2 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-XLight.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/OperatorMono-XLightItalic.otf b/configs/shared/misc/.local/share/fonts/OperatorMono-XLightItalic.otf new file mode 100644 index 000000000000..aa9e2c28ad0a --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/OperatorMono-XLightItalic.otf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/SourceCodePro-Black.ttf b/configs/shared/misc/.local/share/fonts/SourceCodePro-Black.ttf new file mode 100644 index 000000000000..e2422b25fb3b --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/SourceCodePro-Black.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/SourceCodePro-Bold.ttf b/configs/shared/misc/.local/share/fonts/SourceCodePro-Bold.ttf new file mode 100644 index 000000000000..2e545feeb3bb --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/SourceCodePro-Bold.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/SourceCodePro-ExtraLight.ttf b/configs/shared/misc/.local/share/fonts/SourceCodePro-ExtraLight.ttf new file mode 100644 index 000000000000..8a80a6401251 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/SourceCodePro-ExtraLight.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/SourceCodePro-Light.ttf b/configs/shared/misc/.local/share/fonts/SourceCodePro-Light.ttf new file mode 100644 index 000000000000..8f95a47c87b6 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/SourceCodePro-Light.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/SourceCodePro-Medium.ttf b/configs/shared/misc/.local/share/fonts/SourceCodePro-Medium.ttf new file mode 100644 index 000000000000..b7471baa5246 --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/SourceCodePro-Medium.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/SourceCodePro-Regular.ttf b/configs/shared/misc/.local/share/fonts/SourceCodePro-Regular.ttf new file mode 100644 index 000000000000..fa1f90b98aec --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/SourceCodePro-Regular.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/fonts/SourceCodePro-Semibold.ttf b/configs/shared/misc/.local/share/fonts/SourceCodePro-Semibold.ttf new file mode 100644 index 000000000000..77ebab25aaee --- /dev/null +++ b/configs/shared/misc/.local/share/fonts/SourceCodePro-Semibold.ttf Binary files differdiff --git a/configs/shared/misc/.local/share/sounds/gong.mp3 b/configs/shared/misc/.local/share/sounds/gong.mp3 new file mode 100644 index 000000000000..de0220f329de --- /dev/null +++ b/configs/shared/misc/.local/share/sounds/gong.mp3 Binary files differdiff --git a/configs/shared/misc/.local/share/wallpaper/cartoon-outdoors.jpg b/configs/shared/misc/.local/share/wallpaper/cartoon-outdoors.jpg new file mode 100644 index 000000000000..1fdee71f88db --- /dev/null +++ b/configs/shared/misc/.local/share/wallpaper/cartoon-outdoors.jpg Binary files differdiff --git a/configs/shared/misc/.ssh/config b/configs/shared/misc/.ssh/config index 3858ccd5c107..d99315e39dc1 100644 --- a/configs/shared/misc/.ssh/config +++ b/configs/shared/misc/.ssh/config @@ -1,4 +1,4 @@ -Host box +Host desktop Hostname wpcarro.lon.corp.google.com Host cloudtop diff --git a/configs/shared/misc/.unison/cloudtop b/configs/shared/misc/.unison/cloudtop new file mode 100644 index 000000000000..db6ecdae12ad --- /dev/null +++ b/configs/shared/misc/.unison/cloudtop @@ -0,0 +1,7 @@ +root = /usr/local/google/home/wpcarro/cloud +root = ssh://cloudtop//usr/local/google/home/wpcarro/cloud +auto = true +batch = true +backuploc = local +backupsuffix = ~~ +ignore = Name *~ diff --git a/configs/shared/misc/bin/dropbox.py b/configs/shared/misc/bin/dropbox.py new file mode 100755 index 000000000000..c845e112de8b --- /dev/null +++ b/configs/shared/misc/bin/dropbox.py @@ -0,0 +1,1596 @@ +#!/usr/bin/env python3 +# +# Copyright (c) Dropbox, Inc. +# +# dropbox +# Dropbox frontend script +# This file is part of nautilus-dropbox 2019.02.14. +# +# nautilus-dropbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# nautilus-dropbox is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with nautilus-dropbox. If not, see <http://www.gnu.org/licenses/>. +# +from __future__ import with_statement + +import errno +import locale +import optparse +import os +import platform +import shutil +import socket +import subprocess +import sys +import tarfile +import tempfile +import threading +import _thread +import time +import traceback +import urllib.request + +try: + import gpg + gpgme = None +except ImportError: + gpg = None + # Still support gpgme for now. Remove this once we only support 17.04+. + try: + import gpgme + except ImportError: + gpgme = None + +from contextlib import closing, contextmanager +from io import BytesIO +from operator import methodcaller +from os.path import relpath +from posixpath import curdir, sep, pardir, join, abspath, commonprefix + +INFO = "Dropbox is the easiest way to share and store your files online. Want to learn more? Head to" +LINK = "https://www.dropbox.com/" +WARNING = "In order to use Dropbox, you must download the proprietary daemon." +GPG_WARNING = "Note: python3-gpg (python3-gpgme for Ubuntu 16.10 and lower) is not installed, we will not be able to verify binary signatures." +ERROR_CONNECTING = "Trouble connecting to Dropbox servers. Maybe your internet connection is down, or you need to set your http_proxy environment variable." +ERROR_SIGNATURE = "Downloaded binary does not match Dropbox signature, aborting install." +ERROR_INVALID_DROPBOX = "Could not start the Dropbox daemon. Make sure your computer meets the minimum requirements:\nhttps://www.dropbox.com/help/desktop-web/system-requirements#desktop" + +DOWNLOAD_LOCATION_FMT = "https://www.dropbox.com/download?plat=%s" +SIGNATURE_LOCATION_FMT = "https://www.dropbox.com/download?plat=%s&signature=1" + +DOWNLOADING = "Downloading Dropbox... %d%%" +UNPACKING = "Unpacking Dropbox... %d%%" + +PARENT_DIR = os.path.expanduser("~") +DROPBOX_DIST_PATH = "%s/.dropbox-dist" % PARENT_DIR +DROPBOXD_PATH = os.path.join(DROPBOX_DIST_PATH, "dropboxd") +DESKTOP_FILE = "/usr/share/applications/dropbox.desktop" + +enc = locale.getpreferredencoding() + +# Available from https://linux.dropbox.com/fedora/rpm-public-key.asc +DROPBOX_PUBLIC_KEY = b""" +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.0 + +mQENBEt0ibEBCACv4hZRPqwtpU6z8+BB5YZU1a3yjEvg2W68+a6hEwxtCa2U++4dzQ+7EqaU +q5ybQnwtbDdpFpsOi9x31J+PCpufPUfIG694/0rlEpmzl2GWzY8NqfdBFGGm/SPSSwvKbeNc +FMRLu5neo7W9kwvfMbGjHmvUbzBUVpCVKD0OEEf1q/Ii0Qcekx9CMoLvWq7ZwNHEbNnij7ec +nvwNlE2MxNsOSJj+hwZGK+tM19kuYGSKw4b5mR8IyThlgiSLIfpSBh1n2KX+TDdk9GR+57TY +vlRu6nTPu98P05IlrrCP+KF0hYZYOaMvQs9Rmc09tc/eoQlN0kkaBWw9Rv/dvLVc0aUXABEB +AAG0MURyb3Bib3ggQXV0b21hdGljIFNpZ25pbmcgS2V5IDxsaW51eEBkcm9wYm94LmNvbT6J +ATYEEwECACAFAkt0ibECGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRD8kYszUESRLi/z +B/wMscEa15rS+0mIpsORknD7kawKwyda+LHdtZc0hD/73QGFINR2P23UTol/R4nyAFEuYNsF +0C4IAD6y4pL49eZ72IktPrr4H27Q9eXhNZfJhD7BvQMBx75L0F5gSQwuC7GdYNlwSlCD0AAh +Qbi70VBwzeIgITBkMQcJIhLvllYo/AKD7Gv9huy4RLaIoSeofp+2Q0zUHNPl/7zymOqu+5Ox +e1ltuJT/kd/8hU+N5WNxJTSaOK0sF1/wWFM6rWd6XQUP03VyNosAevX5tBo++iD1WY2/lFVU +JkvAvge2WFk3c6tAwZT/tKxspFy4M/tNbDKeyvr685XKJw9ei6GcOGHD +=5rWG +-----END PGP PUBLIC KEY BLOCK----- +""" + + +def console_print(st="", f=sys.stdout, linebreak=True): + f.write(st) + if linebreak: f.write(os.linesep) + +def console_flush(f=sys.stdout): + f.flush() + +def yes_no_question(question): + while True: + console_print(question, linebreak=False) + console_print(" [y/n] ", linebreak=False) + console_flush() + text = input() + if text.lower().startswith("y"): + return True + elif text.lower().startswith("n"): + return False + else: + console_print("Sorry, I didn't understand that. Please type yes or no.") + +def plat(): + if sys.platform.lower().startswith('linux'): + arch = platform.machine() + if (arch[0] == 'i' and + arch[1].isdigit() and + arch[2:4] == '86'): + plat = "x86" + elif arch == 'x86_64': + plat = arch + else: + FatalVisibleError("Platform not supported") + return "lnx.%s" % plat + else: + FatalVisibleError("Platform not supported") + +def is_dropbox_running(): + pidfile = os.path.expanduser("~/.dropbox/dropbox.pid") + + try: + with open(pidfile, "r") as f: + pid = int(f.read()) + with open("/proc/%d/cmdline" % pid, "r") as f: + cmdline = f.read().lower() + except: + cmdline = "" + + return "dropbox" in cmdline + +@contextmanager +def gpg_context(keys): + gpg_conf_contents = b'' + _gpghome = tempfile.mkdtemp(prefix='tmp.gpghome') + + try: + os.environ['GNUPGHOME'] = _gpghome + fp = open(os.path.join(_gpghome, 'gpg.conf'), 'wb') + fp.write(gpg_conf_contents) + fp.close() + if gpg: + ctx = gpg.Context() + else: + ctx = gpgme.Context() + + loaded = [] + for key_file in keys: + if gpg: + ctx.op_import(key_file.read()) + result = ctx.op_import_result() + key = ctx.get_key(result.imports[0].fpr) + else: + result = ctx.import_(key_file) + key = ctx.get_key(result.imports[0][0]) + loaded.append(key) + + ctx.signers = loaded + + yield ctx + finally: + del os.environ['GNUPGHOME'] + shutil.rmtree(_gpghome, ignore_errors=True) + +class SignatureVerifyError(Exception): + pass + +def verify_signature(key_file, sig_file, plain_file): + with gpg_context([key_file]) as ctx: + if gpg: + ctx.op_verify(sig_file.read(), plain_file.read(), None) + result = ctx.op_verify_result() + return result.signatures[0].status == 0 + # gpgme exists + sigs = ctx.verify(sig_file, plain_file, None) + return sigs[0].status == None + + +def download_file_chunk(url, buf): + opener = urllib.request.build_opener() + opener.addheaders = [('User-Agent', "DropboxLinuxDownloader/2019.02.14")] + + with closing(opener.open(url)) as f: + size = int(f.info()['content-length']) + bufsize = int(max(size / 200, 4096)) + progress = 0 + yield (0, True) + while True: + try: + chunk = f.read(bufsize) + progress += len(chunk) + buf.write(chunk) + yield (float(progress)/size, True) + if progress == size: + break + except OSError as e: + if hasattr(e, 'errno') and e.errno == errno.EAGAIN: + # nothing left to read + yield (float(progress)/size, False) + else: + raise + +class DownloadState(object): + def __init__(self): + self.local_file = BytesIO() + + def copy_data(self): + return download_file_chunk(DOWNLOAD_LOCATION_FMT % plat(), self.local_file) + + def unpack(self): + # download signature + signature = BytesIO() + for _ in download_file_chunk(SIGNATURE_LOCATION_FMT % plat(), signature): + pass + signature.seek(0) + self.local_file.seek(0) + + if gpg or gpgme: + if not verify_signature(BytesIO(DROPBOX_PUBLIC_KEY), signature, self.local_file): + raise SignatureVerifyError() + + self.local_file.seek(0) + archive = tarfile.open(fileobj=self.local_file, mode='r:gz') + total_members = len(archive.getmembers()) + for i, member in enumerate(archive.getmembers()): + filename = os.path.join(PARENT_DIR, member.name) + if os.path.exists(filename) and not os.path.isdir(filename): + os.unlink(filename) + archive.extract(member, PARENT_DIR) + yield member.name, i, total_members + archive.close() + + def cancel(self): + if not self.local_file.closed: + self.local_file.close() + + def is_dropbox_valid(self): + """ + Validate that Dropbox runs, so we can show an error + message to the user if it doesn't work. + + Returns True if Dropbox can run, false otherwise. + """ + f = open("/dev/null", "w") + try: + a = subprocess.Popen([DROPBOXD_PATH, "/testrun", "0"], preexec_fn=os.setsid, cwd=os.path.expanduser("~"), + stderr=sys.stderr, stdout=f, close_fds=True) + except Exception as e: + print(e) + return False + + # in seconds + interval = 0.5 + wait_for = 30 + for _ in range(int(wait_for / interval)): + ret_val = a.poll() + if ret_val is None: + time.sleep(interval) + continue + return ret_val == 0 + + return False + + +def load_serialized_images(): + global box_logo_pixbuf, window_icon + import gi + gi.require_version('GdkPixbuf', '2.0') + from gi.repository import GdkPixbuf + box_logo_pixbuf = GdkPixbuf.Pixbuf.new_from_data(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\xff\x1b\x00c\xff\xad\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xff\x02\x00d\xffn\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffp\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcb\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00c\xff\x8e\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00c\xff\x90\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xffN\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\xffP\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00d\xffR\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00d\xff\x92\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00c\xff\xce\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00b\xffr\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffn\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffp\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00e\xffQ\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xce\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffq\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00e\xffQ\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfd\x00b\xff\x91\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00b\xff\x91\x00c\xff\xfd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xcd\x00b\xff4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00d\xffO\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff4\x00b\xff\xcd\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00f\xff2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf2\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffq\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb0\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00d\xffp\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf2\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00b\xff\xae\x00c\xff\xb1\x00j\xff\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00c\xffo\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x1d\x00c\xff\xb0\x00c\xff\xaf\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00d\xffp\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb0\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffO\x00c\xff\xe3\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe3\x00c\xffP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xfc\x00c\xff\x90\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00c\xff\xcc\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xcc\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x03\x00c\xffo\x00c\xff\xf3\x00b\xff\xff\x00b\xff\xff\x00c\xff\xf3\x00d\xffp\x00\xaa\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff\x1c\x00c\xff\xaf\x00c\xff\xb0\x00d\xff\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', GdkPixbuf.Colorspace.RGB, True, 8, 64, 64, 256) + window_icon = GdkPixbuf.Pixbuf.new_from_data(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff2\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xff3\x00d\xff3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00j\xff\x0c\x00b\xff\x8f\x00b\xff\xfc\x00b\xff\xfc\x00b\xff\x8f\x00j\xff\x0c\x00\x00\x00\x00\x00b\xffN\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00d\xffO\x00b\xffN\x00b\xff\xe2\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe2\x00b\xffN\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00d\xffR\x00e\xffQ\x00b\xff\xe4\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xe4\x00e\xffQ\x00\x00\x00\x00\x00b\xff\r\x00d\xff\x92\x00c\xff\xfd\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\r\x00d\xff\x92\x00c\xff\xfd\x00c\xff\xfd\x00d\xff\x92\x00b\xff\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xffe\x00d\xfff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xfff\x00d\xfff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\xff\x0b\x00b\xff\x8c\x00b\xff\xfc\x00b\xff\xfc\x00c\xff\x8d\x00t\xff\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00t\xff\x0b\x00b\xff\x8c\x00b\xff\xfc\x00b\xff\xfc\x00b\xff\x8c\x00t\xff\x0b\x00\x00\x00\x00\x00c\xffK\x00c\xff\xe0\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe1\x00e\xffL\x00e\xffL\x00c\xff\xe1\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe1\x00e\xffL\x00d\xffT\x00c\xff\xe5\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe6\x00c\xffU\x00d\xffT\x00c\xff\xe6\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xe6\x00d\xffT\x00\x00\x00\x00\x00m\xff\x0e\x00b\xff\x94\x00c\xff\xfd\x00c\xff\xfd\x00c\xff\x95\x00i\xff\x11\x00c\xffj\x00d\xffk\x00i\xff\x11\x00c\xff\x95\x00c\xff\xfd\x00c\xff\xfd\x00c\xff\x95\x00m\xff\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff7\x00d\xff8\x00d\xff.\x00b\xff\xc8\x00b\xff\xff\x00b\xff\xff\x00b\xff\xc8\x00g\xff/\x00f\xff7\x00f\xff7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00b\xff\x7f\x00c\xff\xfb\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xfb\x00d\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\xff \x00b\xff\xb6\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00b\xff\xff\x00c\xff\xb7\x00d\xff!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00d\xffW\x00b\xff\xe7\x00b\xff\xe7\x00d\xffW\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\xff\x0f\x00p\xff\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', GdkPixbuf.Colorspace.RGB, True, 8, 16, 16, 64) + +GUI_AVAILABLE = os.environ.get("DISPLAY", '') + +if GUI_AVAILABLE: + def download(): + import gi + gi.require_version('Gdk', '3.0') + gi.require_version('Gtk', '3.0') + from gi.repository import GObject + from gi.repository import Gdk + from gi.repository import Gtk + from gi.repository import Pango + import webbrowser + + GObject.threads_init() + + load_serialized_images() + + global FatalVisibleError + def FatalVisibleError(s): + error = Gtk.MessageDialog(parent = None, + flags = Gtk.DialogFlags.MODAL, + type = Gtk.MessageType.ERROR, + buttons = Gtk.ButtonsType.OK, + message_format = s) + error.set_title("Error") + error.run() + Gtk.main_quit() + sys.exit(-1) + + class GeneratorTask(object): + def __init__(self, generator, loop_callback, on_done=None, on_exception=None): + self.generator = generator + self.loop_callback = loop_callback + self.on_done = on_done + self.on_exception = on_exception + + def _run(self, *args, **kwargs): + self._stopped = False + try: + for ret in self.generator(*args, **kwargs): + if ret is None: + ret = () + if not isinstance(ret, tuple): + ret = (ret,) + GObject.idle_add(self.loop_callback, *ret) + + if self._stopped: + _thread.exit() + except Exception as e: + print(e) + if self.on_exception is not None: + GObject.idle_add(self.on_exception, e) + else: + if self.on_done is not None: + GObject.idle_add(self.on_done) + + def start(self, *args, **kwargs): + t = threading.Thread(target=self._run, args=args, kwargs=kwargs) + t.setDaemon(True) + t.start() + + def stop(self): + self._stopped = True + + class DownloadDialog(Gtk.Dialog): + def handle_delete_event(self, wid, ev, data=None): + self.handle_cancel(wid) + + def handle_dont_show_toggle(self, button, data=None): + reroll_autostart(not button.get_active()) + + def handle_cancel(self, button): + if self.task: + self.task.stop() + if self.download: + self.download.cancel() + Gtk.main_quit() + self.user_cancelled = True + + def handle_ok(self, button): + # begin download + self.ok.hide() + self.download = DownloadState() + + self.label.hide() + if self.dont_show_again_align is not None: + self.dont_show_again_align.hide() + self.progress.show() + + def download_progress(progress, status): + if not status: + self.task.stop() + self.update_progress(DOWNLOADING, progress) + + def finished(): + self.update_progress(DOWNLOADING, 1.0) + self.unpack_dropbox() + + def error(ex): + FatalVisibleError(ERROR_CONNECTING) + + self.update_progress(DOWNLOADING, 0) + self.task = GeneratorTask(self.download.copy_data, + download_progress, + finished, error).start() + + def update_progress(self, text, fraction): + self.progress.set_text(text % int(fraction*100)) + self.progress.set_fraction(fraction) + + def unpack_dropbox(self): + def unpack_progress(name, i, total): + self.update_progress(UNPACKING, float(i)/total) + + def finished(): + self.update_progress(UNPACKING, 1.0) + if not self.download.is_dropbox_valid(): + FatalVisibleError(ERROR_INVALID_DROPBOX) + Gtk.main_quit() + + def error(ex): + if isinstance(ex, SignatureVerifyError): + FatalVisibleError(ERROR_SIGNATURE) + else: + FatalVisibleError(ERROR_CONNECTING) + + self.task = GeneratorTask(self.download.unpack, + unpack_progress, + finished, error).start() + + def mouse_down(self, widget, event): + if self.hovering: + self.clicked_link = True + + def mouse_up(self, widget, event): + if self.clicked_link: + webbrowser.open(LINK) + self.clicked_link = False + + def label_motion(self, widget, event): + offx, offy = self.label.get_layout_offsets() + layout = self.label.get_layout() + index = layout.xy_to_index(int((offx+event.x)*Pango.SCALE), + int((offy+event.y)*Pango.SCALE))[1] + link_index = layout.get_text().find(LINK) + if index >= link_index and index < link_index+len(LINK): + self.hovering = True + self.label_box.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2)) + else: + self.hovering = False + self.label_box.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.ARROW)) + + + def __init__(self): + super(DownloadDialog, self).__init__(parent = None, + title = "Dropbox Installation") + + self.download = None + self.hovering = False + self.clicked_link = False + self.user_cancelled = False + self.task = None + + self.ok = ok = Gtk.Button(stock=Gtk.STOCK_OK) + ok.connect('clicked', self.handle_ok) + self.action_area.add(ok) + ok.show() + + cancel = Gtk.Button(stock=Gtk.STOCK_CANCEL) + cancel.connect('clicked', self.handle_cancel) + self.action_area.add(cancel) + cancel.show() + + self.connect('delete_event', self.handle_delete_event) + + self.box_logo = Gtk.Image.new_from_pixbuf(box_logo_pixbuf) + self.box_logo.show() + + self.set_icon(window_icon) + + self.progress = Gtk.ProgressBar() + self.progress.set_property('width-request', 300) + self.progress.set_property('show-text', True) + + self.label = Gtk.Label() + GPG_WARNING_MSG = ("\n\n" + GPG_WARNING) if not gpg and not gpgme else "" + self.label.set_markup('%s <span foreground="#000099" underline="single" weight="bold">%s</span>\n\n%s%s' % (INFO, LINK, WARNING, GPG_WARNING_MSG)) + self.label.set_line_wrap(True) + self.label.set_property('width-request', 300) + self.label.show() + + self.label_box = Gtk.EventBox() + self.label_box.add(self.label) + self.label_box.connect("button-release-event", self.mouse_up) + self.label_box.connect("button-press-event", self.mouse_down) + self.label_box.connect("motion-notify-event", self.label_motion) + + self.label_box.show() + def on_realize(widget): + self.label_box.add_events(Gdk.EventMask.POINTER_MOTION_MASK) + self.label_box.connect("realize", on_realize) + + self.hbox = Gtk.HBox(spacing=10) + self.hbox.set_property('border-width',10) + self.hbox.pack_start(self.box_logo, False, False, 0) + self.hbox.pack_start(self.label_box, False, False, 0) + self.hbox.pack_start(self.progress, False, False, 0) + self.hbox.show() + + self.vbox.add(self.hbox) + + self.dont_show_again_align = None + + try: + if can_reroll_autostart(): + dont_show_again = Gtk.CheckButton.new_with_mnemonic("_Don't show this again") + dont_show_again.connect('toggled', self.handle_dont_show_toggle) + dont_show_again.show() + + self.dont_show_again_align = Gtk.Alignment(xalign=1.0, yalign=0.0, xscale=0.0, yscale=0.0) + self.dont_show_again_align.add(dont_show_again) + self.dont_show_again_align.show() + + hbox = Gtk.HBox() + hbox.set_property('border-width', 10) + hbox.pack_start(self.dont_show_again_align, True, True, 0) + hbox.show() + + self.vbox.add(hbox) + + self.set_resizable(False) + except: + traceback.print_exc() + + self.ok.grab_focus() + + dialog = DownloadDialog() + dialog.show() + Gtk.main() + if dialog.user_cancelled: + raise Exception("user cancelled download!!!") +else: + def download(): + global FatalVisibleError + def FatalVisibleError(s): + console_print("\nError: %s" % s, f=sys.stderr) + sys.exit(-1) + + + ESC = "\x1b" + save = ESC+"7" + unsave = ESC+"8" + erase_to_start = ESC+"[1K" + write = sys.stdout.write + flush = sys.stdout.flush + + last_progress = [None, None] + def setprogress(text, frac): + if last_progress == [text, frac]: + return + if sys.stdout.isatty(): + write(erase_to_start) + write(unsave) + console_print(text % int(100*frac), linebreak=not sys.stdout.isatty()) + if sys.stdout.isatty(): + flush() + last_progress[0], last_progress[1] = text, frac + + console_print() + if sys.stdout.isatty(): + write(save) + flush() + console_print("%s %s\n" % (INFO, LINK)) + GPG_WARNING_MSG = ("\n%s" % GPG_WARNING) if not gpg and not gpgme else "" + + if not yes_no_question("%s%s" % (WARNING, GPG_WARNING_MSG)): + return + + download = DownloadState() + + try: + for progress, status in download.copy_data(): + if not status: + break + setprogress(DOWNLOADING, progress) + except Exception: + traceback.print_exc() + FatalVisibleError(ERROR_CONNECTING) + else: + setprogress(DOWNLOADING, 1.0) + console_print() + write(save) + + try: + for _, i, total in download.unpack(): + setprogress(UNPACKING, float(i)/total) + except SignatureVerifyError: + traceback.print_exc() + FatalVisibleError(ERROR_SIGNATURE) + except Exception: + traceback.print_exc() + FatalVisibleError(ERROR_CONNECTING) + else: + setprogress(UNPACKING, 1.0) + + if not download.is_dropbox_valid(): + FatalVisibleError(ERROR_INVALID_DROPBOX) + + console_print() + +class CommandTicker(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + self.stop_event = threading.Event() + + def stop(self): + self.stop_event.set() + + def run(self): + ticks = ['[. ]', '[.. ]', '[...]', '[ ..]', '[ .]', '[ ]'] + i = 0 + first = True + while True: + self.stop_event.wait(0.25) + if self.stop_event.isSet(): break + if i == len(ticks): + first = False + i = 0 + if not first: + sys.stderr.write("\r%s\r" % ticks[i]) + sys.stderr.flush() + i += 1 + sys.stderr.flush() + + +class DropboxCommand(object): + class CouldntConnectError(Exception): pass + class BadConnectionError(Exception): pass + class EOFError(Exception): pass + class CommandError(Exception): pass + + def __init__(self, timeout=5): + self.s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.s.settimeout(timeout) + try: + self.s.connect(os.path.expanduser('~/.dropbox/command_socket')) + except socket.error: + raise DropboxCommand.CouldntConnectError() + self.f = self.s.makefile("rw", 4096) + + def close(self): + self.f.close() + self.s.close() + + def __readline(self): + try: + toret = self.f.readline().rstrip("\n") + except socket.error: + raise DropboxCommand.BadConnectionError() + if toret == '': + raise DropboxCommand.EOFError() + else: + return toret + + # atttribute doesn't exist, i know what you want + def send_command(self, name, args): + self.f.write(name) + self.f.write("\n") + self.f.writelines(("\t".join([k] + ([v] + if isinstance(v, str) else + list(v))) + "\n") + for k,v in args.items()) + self.f.write("done\n") + + self.f.flush() + + # Start a ticker + ticker_thread = CommandTicker() + ticker_thread.start() + + # This is the potentially long-running call. + try: + ok = self.__readline() == "ok" + except KeyboardInterrupt: + raise DropboxCommand.BadConnectionError("Keyboard interruption detected") + finally: + # Tell the ticker to stop. + ticker_thread.stop() + ticker_thread.join() + + if ok: + toret = {} + for i in range(21): + if i == 20: + raise Exception("close this connection!") + + line = self.__readline() + if line == "done": + break + + argval = line.split("\t") + toret[argval[0]] = argval[1:] + + return toret + else: + problems = [] + for i in range(21): + if i == 20: + raise Exception("close this connection!") + + line = self.__readline() + if line == "done": + break + + problems.append(line) + + raise DropboxCommand.CommandError("\n".join(problems)) + + # this is the hotness, auto marshalling + def __getattr__(self, name): + try: + return super(DropboxCommand, self).__getattr__(name) + except: + def __spec_command(**kw): + return self.send_command(str(name), kw) + self.__setattr__(name, __spec_command) + return __spec_command + +commands = {} +aliases = {} + +def command(meth): + global commands, aliases + assert meth.__doc__, "All commands need properly formatted docstrings (even %r!!)" % meth + if hasattr(meth, 'im_func'): # bound method, if we ever have one + meth = meth.im_func + commands[meth.__name__] = meth + meth_aliases = [str(alias) for alias in aliases.keys() if aliases[alias].__name__ == meth.__name__] + if meth_aliases: + meth.__doc__ += "\nAliases: %s" % ",".join(meth_aliases) + return meth + +def alias(name): + def decorator(meth): + global commands, aliases + assert name not in commands, "This alias is the name of a command." + aliases[name] = meth + return meth + return decorator + +def requires_dropbox_running(meth): + def newmeth(*n, **kw): + if is_dropbox_running(): + return meth(*n, **kw) + else: + console_print("Dropbox isn't running!") + newmeth.__name__ = meth.__name__ + newmeth.__doc__ = meth.__doc__ + return newmeth + +def start_dropbox(): + if os.access(DROPBOXD_PATH, os.X_OK): + f = open("/dev/null", "w") + # we don't reap the child because we're gonna die anyway, let init do it + subprocess.Popen([DROPBOXD_PATH], preexec_fn=os.setsid, cwd=os.path.expanduser("~"), + stderr=sys.stderr, stdout=f, close_fds=True) + + # in seconds + interval = 0.5 + wait_for = 60 + for _ in range(int(wait_for / interval)): + if is_dropbox_running(): + return True + # back off from connect for a while + time.sleep(interval) + + return False + else: + return False + +# Extracted and modified from os.cmd.Cmd +def columnize(list, display_list=None, display_width=None): + if not list: + console_print("<empty>") + return + + non_str = [i for i in range(len(list)) if not (isinstance(list[i], str))] + if non_str: + raise TypeError("list[i] not a string for i in %s" % + ", ".join(map(str, non_str))) + + if not display_width: + d = os.popen('stty size', 'r').read().split() + if d: + display_width = int(d[1]) + else: + for item in list: + console_print(item) + return + + if not display_list: + display_list = list + + size = len(list) + if size == 1: + console_print(display_list[0]) + return + + for nrows in range(1, len(list)): + ncols = (size+nrows-1) // nrows + colwidths = [] + totwidth = -2 + for col in range(ncols): + colwidth = 0 + for row in range(nrows): + i = row + nrows*col + if i >= size: + break + x = list[i] + colwidth = max(colwidth, len(x)) + colwidths.append(colwidth) + totwidth += colwidth + 2 + if totwidth > display_width: + break + if totwidth <= display_width: + break + else: + nrows = len(list) + ncols = 1 + colwidths = [0] + lines = [] + for row in range(nrows): + texts = [] + display_texts = [] + for col in range(ncols): + i = row + nrows*col + if i >= size: + x = "" + y = "" + else: + x = list[i] + y = display_list[i] + texts.append(x) + display_texts.append(y) + while texts and not texts[-1]: + del texts[-1] + original_texts = texts[:] + for col in range(len(texts)): + texts[col] = texts[col].ljust(colwidths[col]) + texts[col] = texts[col].replace(original_texts[col], display_texts[col]) + line = " ".join(texts) + lines.append(line) + for line in lines: + console_print(line) + +@command +def update(args): + """download latest version of Dropbox +dropbox update + +Downloads the latest version of Dropbox. This should not be required +normally, as Dropbox automatically updates itself. + """ + download() + +@command +@requires_dropbox_running +@alias('stat') +def filestatus(args): + """get current sync status of one or more files +dropbox filestatus [-l] [-a] [FILE]... + +Prints the current status of each FILE. + +options: + -l --list Prints out information in a format similar to ls. Works best when your console supports color :) + -a --all Do not ignore entries starting with "." + """ + global enc + + oparser = optparse.OptionParser() + oparser.add_option("-l", "--list", action="store_true", dest="list") + oparser.add_option("-a", "--all", action="store_true", dest="all") + (options, args) = oparser.parse_args(args) + + try: + with closing(DropboxCommand()) as dc: + if options.list: + # Listing. + + # Separate directories from files. + if len(args) == 0: + dirs, nondirs = ["."], [] + else: + dirs, nondirs = [], [] + + for a in args: + try: + (dirs if os.path.isdir(a) else nondirs).append(a) + except UnicodeDecodeError: + continue + + if len(dirs) == 0 and len(nondirs) == 0: + #TODO: why? + exit(1) + + dirs.sort(key=methodcaller('lower')) + nondirs.sort(key=methodcaller('lower')) + + # Gets a string representation for a path. + def path_to_string(file_path): + if not os.path.exists(file_path): + path = "%s (File doesn't exist!)" % os.path.basename(file_path) + return (path, path) + try: + status = dc.icon_overlay_file_status(path=file_path).get('status', [None])[0] + except DropboxCommand.CommandError as e: + path = "%s (%s)" % (os.path.basename(file_path), e) + return (path, path) + + env_term = os.environ.get('TERM','') + supports_color = (sys.stderr.isatty() and ( + env_term.startswith('vt') or + env_term.startswith('linux') or + 'xterm' in env_term or + 'color' in env_term + ) + ) + + # TODO: Test when you don't support color. + if not supports_color: + path = os.path.basename(file_path) + return (path, path) + + if status == "up to date": + init, cleanup = "\x1b[32;1m", "\x1b[0m" + elif status == "syncing": + init, cleanup = "\x1b[36;1m", "\x1b[0m" + elif status == "unsyncable": + init, cleanup = "\x1b[41;1m", "\x1b[0m" + elif status == "selsync": + init, cleanup = "\x1b[37;1m", "\x1b[0m" + else: + init, cleanup = '', '' + + path = os.path.basename(file_path) + return (path, "%s%s%s" % (init, path, cleanup)) + + # Prints a directory. + def print_directory(name): + clean_paths = [] + formatted_paths = [] + for subname in sorted(os.listdir(name), key=methodcaller('lower')): + if type(subname) != str: + continue + + if not options.all and subname[0] == '.': + continue + + try: + clean, formatted = path_to_string(os.path.abspath(os.path.join(name, subname))) + clean_paths.append(clean) + formatted_paths.append(formatted) + except (UnicodeEncodeError, UnicodeDecodeError): + continue + + columnize(clean_paths, formatted_paths) + + try: + if len(dirs) == 1 and len(nondirs) == 0: + print_directory(dirs[0]) + else: + nondir_formatted_paths = [] + nondir_clean_paths = [] + for name in nondirs: + try: + clean, formatted = path_to_string(os.path.abspath(name)) + nondir_clean_paths.append(clean) + nondir_formatted_paths.append(formatted) + except (UnicodeEncodeError, UnicodeDecodeError): + continue + + if nondir_clean_paths: + columnize(nondir_clean_paths, nondir_formatted_paths) + + if len(nondirs) == 0: + console_print(dirs[0] + ":") + print_directory(dirs[0]) + dirs = dirs[1:] + + for name in dirs: + console_print() + console_print(name + ":") + print_directory(name) + + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + else: + if len(args) == 0: + args = [name for name in sorted(os.listdir("."), key=methodcaller('lower')) if type(name) == str] + if len(args) == 0: + # Bail early if there's nothing to list to avoid crashing on indent below + console_print("<empty>") + return + indent = max(len(st)+1 for st in args) + for file in args: + + try: + if type(file) is not str: + file = file.decode(enc) + fp = os.path.abspath(file) + except (UnicodeEncodeError, UnicodeDecodeError): + continue + if not os.path.exists(fp): + console_print("%-*s %s" % \ + (indent, file+':', "File doesn't exist")) + continue + + try: + status = dc.icon_overlay_file_status(path=fp).get('status', ['unknown'])[0] + console_print("%-*s %s" % (indent, file+':', status)) + except DropboxCommand.CommandError as e: + console_print("%-*s %s" % (indent, file+':', e)) + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +@command +@requires_dropbox_running +def ls(args): + """list directory contents with current sync status +dropbox ls [FILE]... + +This is an alias for filestatus -l + """ + return filestatus(["-l"] + args) + +@command +@requires_dropbox_running +def puburl(args): + """get public url of a file in your Dropbox's public folder +dropbox puburl FILE + +Prints out a public url for FILE (which must be in your public folder). + """ + if len(args) != 1: + console_print(puburl.__doc__,linebreak=False) + return + + try: + with closing(DropboxCommand()) as dc: + try: + console_print(dc.get_public_link(path=os.path.abspath(args[0])).get('link', ['No Link'])[0]) + except DropboxCommand.CommandError as e: + console_print("Couldn't get public url: " + str(e)) + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +@command +@requires_dropbox_running +def sharelink(args): + """get a shared link for a file in your Dropbox +dropbox sharelink FILE + +Prints out a shared link for FILE. + """ + if len(args) != 1: + console_print(sharelink.__doc__, linebreak=False) + return + + try: + with closing(DropboxCommand()) as dc: + try: + path = os.path.abspath(args[0]) + link = dc.get_shared_link(path=path).get('link', ['No link'])[0] + console_print(link) + except DropboxCommand.CommandError as e: + console_print("Couldn't get shared link: " + str(e)) + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +@command +@requires_dropbox_running +def proxy(args): + """set proxy settings for Dropbox +dropbox proxy MODE [TYPE] [HOST] [PORT] [USERNAME] [PASSWORD] + +Set proxy settings for Dropbox. + +MODE - one of "none", "auto", "manual" +TYPE - one of "http", "socks4", "socks5" (only valid with "manual" mode) +HOST - proxy hostname (only valid with "manual" mode) +PORT - proxy port (only valid with "manual" mode) +USERNAME - (optional) proxy username (only valid with "manual" mode) +PASSWORD - (optional) proxy password (only valid with "manual" mode) + """ + mode = None + type_ = None + if len(args) >= 1: + mode = args[0].lower() + if len(args) >= 2: + type_ = args[1].lower() + + if (len(args) == 0 or + mode not in ['none', 'auto', 'manual'] or + (mode == 'manual' and len(args) not in (4, 6)) or + (mode != 'manual' and len(args) != 1) or + (mode == 'manual' and type_ not in ['http', 'socks4', 'socks5'])): + # Print help + console_print(proxy.__doc__, linebreak=False) + return + + ARGS = ['mode', 'type', 'host', 'port', 'username', 'password'] + + # Load the args into a dictionary + kwargs = dict(zip(ARGS, args)) + + # Re-set these two because they were coerced to lower case + kwargs['mode'] = mode + if type_: + kwargs['type'] = type_ + + try: + with closing(DropboxCommand()) as dc: + try: + dc.set_proxy_settings(**kwargs) + console_print('set') + except DropboxCommand.CommandError as e: + console_print("Couldn't set proxy: " + str(e)) + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +@command +@requires_dropbox_running +def throttle(args): + """set bandwidth limits for Dropbox +dropbox throttle DOWNLOAD UPLOAD + +Set bandwidth limits for file sync. + +DOWNLOAD - either "unlimited" or a manual limit in KB/s +UPLOAD - one of "unlimited", "auto", or a manual limit in KB/s + """ + if len(args) != 2: + console_print(throttle.__doc__, linebreak=False) + return + + downlimit = args[0].lower() + uplimit = args[1].lower() + + download_limit = None + download_mode = None + if downlimit == 'unlimited': + download_mode = downlimit + else: + try: + download_limit = int(downlimit) + download_mode = 'manual' + except ValueError: + console_print(throttle.__doc__, linebreak=False) + return + + upload_limit = None + upload_mode = None + if uplimit in ['unlimited', 'auto']: + upload_mode = uplimit + else: + try: + upload_limit = int(uplimit) + upload_mode = 'manual' + except ValueError: + console_print(throttle.__doc__, linebreak=False) + return + + kwargs = { + 'download_mode': download_mode, + 'upload_mode': upload_mode, + } + if download_limit: + kwargs['download_limit'] = str(download_limit) + if upload_limit: + kwargs['upload_limit'] = str(upload_limit) + + try: + with closing(DropboxCommand()) as dc: + try: + dc.set_bandwidth_limits(**kwargs) + console_print('set') + except DropboxCommand.CommandError as e: + console_print("Couldn't set bandwidth limits: " + str(e)) + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +@command +@requires_dropbox_running +def status(args): + """get current status of the dropboxd +dropbox status + +Prints out the current status of the Dropbox daemon. + """ + if len(args) != 0: + console_print(status.__doc__,linebreak=False) + return + + try: + with closing(DropboxCommand()) as dc: + try: + lines = dc.get_dropbox_status()['status'] + if len(lines) == 0: + console_print('Idle') + else: + for line in lines: + console_print(line) + grab_link_url_if_necessary() + except KeyError: + console_print("Couldn't get status: daemon isn't responding") + except DropboxCommand.CommandError as e: + console_print("Couldn't get status: " + str(e)) + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +@command +def running(argv): + """return whether Dropbox is running +dropbox running + +Returns 1 if running, and 0 if not running. + """ + return int(is_dropbox_running()) + +@command +@requires_dropbox_running +def stop(args): + """stop dropboxd +dropbox stop + +Stops the Dropbox daemon. + """ + try: + with closing(DropboxCommand()) as dc: + try: + dc.tray_action_hard_exit() + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +#returns true if link is necessary +def grab_link_url_if_necessary(): + try: + with closing(DropboxCommand()) as dc: + try: + link_url = dc.needs_link().get("link_url", None) + if link_url is not None: + console_print("To link this computer to a Dropbox account, visit the following url:\n%s" % link_url[0]) + return True + else: + return False + except DropboxCommand.CommandError: + pass + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + +@command +@requires_dropbox_running +def lansync(argv): + """enables or disables LAN sync +dropbox lansync [y/n] + +options: + y Dropbox will use LAN sync (default) + n Dropbox will not use LAN sync + """ + if len(argv) != 1: + console_print(lansync.__doc__, linebreak=False) + return + + s = argv[0].lower() + if s.startswith('y') or s.startswith('-y'): + should_lansync = True + elif s.startswith('n') or s.startswith('-n'): + should_lansync = False + else: + should_lansync = None + + if should_lansync is None: + console_print(lansync.__doc__,linebreak=False) + else: + with closing(DropboxCommand()) as dc: + dc.set_lan_sync(lansync='enabled' if should_lansync else 'disabled') + + +@command +@requires_dropbox_running +def exclude(args): + """ignores/excludes a directory from syncing +dropbox exclude [list] +dropbox exclude add [DIRECTORY] [DIRECTORY] ... +dropbox exclude remove [DIRECTORY] [DIRECTORY] ... + +"list" prints a list of directories currently excluded from syncing. +"add" adds one or more directories to the exclusion list, then +resynchronizes Dropbox. +"remove" removes one or more directories from the exclusion list, then +resynchronizes Dropbox. + +With no arguments, executes "list". + +Any specified path must be within Dropbox. + """ + if len(args) == 0: + try: + with closing(DropboxCommand()) as dc: + try: + lines = [relpath(path) for path in dc.get_ignore_set()['ignore_set']] + lines.sort() + if len(lines) == 0: + console_print('No directories are being ignored.') + else: + console_print('Excluded: ') + for line in lines: + console_print(str(line)) + except KeyError: + console_print("Couldn't get ignore set: daemon isn't responding") + except DropboxCommand.CommandError as e: + if e.args[0].startswith("No command exists by that name"): + console_print("This version of the client does not support this command.") + else: + console_print("Couldn't get ignore set: " + str(e)) + except DropboxCommand.BadConnectionError: + console_print("Dropbox isn't responding!") + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + elif len(args) == 1 and args[0] == "list": + exclude([]) + elif len(args) >= 2: + sub_command = args[0] + paths = args[1:] + absolute_paths = [os.path.abspath(path) for path in paths] + if sub_command == "add": + try: + with closing(DropboxCommand(timeout=None)) as dc: + try: + result = dc.ignore_set_add(paths=absolute_paths) + if result["ignored"]: + console_print("Excluded: ") + lines = [relpath(path) for path in result["ignored"]] + for line in lines: + console_print(str(line)) + except KeyError: + console_print("Couldn't add ignore path: daemon isn't responding") + except DropboxCommand.CommandError as e: + if e.args[0].startswith("No command exists by that name"): + console_print("This version of the client does not support this command.") + else: + console_print("Couldn't get ignore set: " + str(e)) + except DropboxCommand.BadConnectionError as e: + console_print("Dropbox isn't responding! [%s]" % e) + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + elif sub_command == "remove": + try: + with closing(DropboxCommand(timeout=None)) as dc: + try: + result = dc.ignore_set_remove(paths=absolute_paths) + if result["removed"]: + console_print("No longer excluded: ") + lines = [relpath(path) for path in result["removed"]] + for line in lines: + console_print(str(line)) + except KeyError: + console_print("Couldn't remove ignore path: daemon isn't responding") + except DropboxCommand.CommandError as e: + if e.args[0].startswith("No command exists by that name"): + console_print("This version of the client does not support this command.") + else: + console_print("Couldn't get ignore set: " + str(e)) + except DropboxCommand.BadConnectionError as e: + console_print("Dropbox isn't responding! [%s]" % e) + except DropboxCommand.EOFError: + console_print("Dropbox daemon stopped.") + except DropboxCommand.CouldntConnectError: + console_print("Dropbox isn't running!") + else: + console_print(exclude.__doc__, linebreak=False) + return + else: + console_print(exclude.__doc__, linebreak=False) + return + +@command +def start(argv): + """start dropboxd +dropbox start [-i] + +Starts the Dropbox daemon, dropboxd. If dropboxd is already running, +this will do nothing. + +options: + -i --install auto install dropboxd if not available on the system + """ + + should_install = "-i" in argv or "--install" in argv + + # first check if dropbox is already running + if is_dropbox_running(): + if not grab_link_url_if_necessary(): + console_print("Dropbox is already running!") + return + + console_print("Starting Dropbox...", linebreak=False) + console_flush() + if not start_dropbox(): + if not should_install: + console_print() + console_print("The Dropbox daemon is not installed!") + console_print("Run \"dropbox start -i\" to install the daemon") + return + + # install dropbox!!! + try: + download() + except: + traceback.print_exc() + else: + if GUI_AVAILABLE: + start_dropbox() + console_print("Done!") + else: + if start_dropbox(): + if not grab_link_url_if_necessary(): + console_print("Done!") + else: + if not grab_link_url_if_necessary(): + console_print("Done!") + + +def can_reroll_autostart(): + return ".config" in os.listdir(os.path.expanduser('~')) + +def reroll_autostart(should_autostart): + home_dir = os.path.expanduser('~') + contents = os.listdir(home_dir) + + # UBUNTU + if ".config" in contents: + autostart_dir = os.path.join(home_dir, ".config", "autostart") + autostart_link = os.path.join(autostart_dir, "dropbox.desktop") + if should_autostart: + if os.path.exists(DESKTOP_FILE): + if not os.path.exists(autostart_dir): + os.makedirs(autostart_dir) + shutil.copyfile(DESKTOP_FILE, autostart_link) + elif os.path.exists(autostart_link): + os.remove(autostart_link) + + + +@command +def autostart(argv): + """automatically start Dropbox at login +dropbox autostart [y/n] + +options: + n Dropbox will not start automatically at login + y Dropbox will start automatically at login (default) + +Note: May only work on current Ubuntu distributions. + """ + if len(argv) != 1: + console_print(''.join(autostart.__doc__.split('\n', 1)[1:])) + return + + s = argv[0].lower() + if s.startswith('y') or s.startswith('-y'): + should_autostart = True + elif s.startswith('n') or s.startswith('-n'): + should_autostart = False + else: + should_autostart = None + + if should_autostart is None: + console_print(autostart.__doc__,linebreak=False) + else: + reroll_autostart(should_autostart) + +@command +def version(argv): + """print version information for Dropbox +dropbox version + +Prints the version information for the Dropbox proprietary daemon, if +it's installed, and the Dropbox command-line interface. + """ + dropbox_daemon_version = "Not installed" + try: + with open(os.path.join(DROPBOX_DIST_PATH, 'VERSION')) as f: + dropbox_daemon_version = f.read().strip() + except OSError: + pass + + console_print("Dropbox daemon version: %s" % dropbox_daemon_version) + console_print("Dropbox command-line interface version: 2019.02.14") + +@command +def help(argv): + """provide help +dropbox help [COMMAND] + +With no arguments, print a list of commands and a short description of +each. With a command, print descriptive help on how to use the +command. + """ + if not argv: + return usage() + for command in commands: + if command == argv[0]: + console_print(commands[command].__doc__.split('\n', 1)[1].strip()) + return + for alias in aliases: + if alias == argv[0]: + console_print(aliases[alias].__doc__.split('\n', 1)[1].strip()) + return + console_print("unknown command '%s'" % argv[0], f=sys.stderr) + +def usage(): + console_print("Dropbox command-line interface\n") + console_print("commands:\n") + console_print("Note: use dropbox help <command> to view usage for a specific command.\n") + out = [] + for command in commands: + out.append((command, commands[command].__doc__.splitlines()[0])) + out.sort(key=lambda x: x[0]) + spacing = max(len(o[0])+3 for o in out) + for o in out: + console_print(" %-*s%s" % (spacing, o[0], o[1])) + +def main(argv): + global commands + + # now we need to find out if one of the commands are in the + # argv list, and if so split the list at the point to + # separate the argv list at that point + cut = None + for i in range(len(argv)): + if argv[i] in commands or argv[i] in aliases: + cut = i + break + + if cut == None: + usage() + os._exit(0) + return + + # lol no options for now + globaloptionparser = optparse.OptionParser() + globaloptionparser.parse_args(argv[0:i]) + + # now dispatch and run + result = None + if argv[i] in commands: + result = commands[argv[i]](argv[i+1:]) + elif argv[i] in aliases: + result = aliases[argv[i]](argv[i+1:]) + + # flush, in case output is rerouted to a file. + console_flush() + + # done + return result + +if __name__ == "__main__": + ret = main(sys.argv) + if ret is not None: + sys.exit(ret) diff --git a/configs/shared/misc/bin/lf b/configs/shared/misc/bin/lf new file mode 100755 index 000000000000..4bca9730754b --- /dev/null +++ b/configs/shared/misc/bin/lf Binary files differdiff --git a/configs/shared/shell/.profile b/configs/shared/shell/.profile new file mode 100644 index 000000000000..e94dd20db6fd --- /dev/null +++ b/configs/shared/shell/.profile @@ -0,0 +1,22 @@ +# Some programs read from ~/.profile for values. It's best to set environment +# variables here instead of in ~/.zshrc or similar files, which are sourced +# everytime a new shell is created. The ~/.profile, on the other hand, is +# typically sourced only once at login. + +PATH="$PATH:$HOME/bin" + +# Application preferences +export BROWSER=google-chrome +export TERMINAL=st +export EDITOR=emacsclient +export ALTERNATE_EDITOR=nvim + +# Application configuration +export FZF_DEFAULT_COMMAND='fd --hidden --follow --exclude ".git"' +export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" + +export DOTFILES="$HOME/Dropbox/dotfiles" +export ORG_DIRECTORY="$HOME/Dropbox/org" + +# Set environment variables for Nix +source ~/.nix-profile/etc/profile.d/nix.sh diff --git a/configs/shared/tmux/.tmux.conf b/configs/shared/tmux/.tmux.conf index f2eff9bc7cf4..9c2124885c02 100644 --- a/configs/shared/tmux/.tmux.conf +++ b/configs/shared/tmux/.tmux.conf @@ -18,7 +18,6 @@ set -g @copycat_next 'p' set -g @copycat_prev 'n' set -g @plugin 'arcticicestudio/nord-tmux' -# set -g @plugin 'tmux-plugins/tmux-yank' ################################################################################ # Context Helpers @@ -39,8 +38,8 @@ is_vim_or_emacs="ps -o state= -o comm= -t '#{pane_tty}' \ # change tmux leader unbind C-b -set -g prefix C-q -bind C-q send-prefix +set -g prefix C-y +bind C-y send-prefix ################################################################################ @@ -48,17 +47,14 @@ bind C-q send-prefix ################################################################################ # COLORS! -set -g default-terminal "screen-256color" -set-option -sa terminal-overrides ",xterm*:Tc" +set -g default-terminal "tmux" +set-option -sa terminal-overrides ",*256col*:Tc" ################################################################################ # Copy Paste ################################################################################ -# Copy-paste integration -set-option -g default-command "reattach-to-user-namespace -l zsh" - # copy text like it's Vim bind -n Escape if-shell "${is_vim_or_emacs}" "send-keys Escape" copy-mode @@ -67,17 +63,10 @@ setw -g mode-keys vi # Setup 'v' to begin selection as in Vim bind -Tcopy-mode-vi v send -X begin-selection -bind -Tcopy-mode-vi y send -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy" +bind -Tcopy-mode-vi y send -X copy-pipe-and-cancel "xclip -selection clipboard -i" bind -Tcopy-mode-vi Escape send -X cancel bind -Tcopy-mode-vi V send -X rectangle-toggle -# Update default binding of `Enter` to also use copy-pipe -unbind -Tcopy-mode Enter -bind -Tcopy-mode Enter send -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy" - -# Bind ']' to use pbpaste -bind ] run "reattach-to-user-namespace pbpaste | tmux load-buffer - && tmux paste-buffer" - ################################################################################ # Windows diff --git a/configs/shared/x_server/.Xmodmap b/configs/shared/x_server/.Xmodmap new file mode 100644 index 000000000000..518793b86705 --- /dev/null +++ b/configs/shared/x_server/.Xmodmap @@ -0,0 +1,7 @@ +! remap caps-lock to escape +remove Lock = Caps_Lock +keysym Caps_Lock = Escape + +! swap ctrl and super (similar to OSX) -- currently not working +! remove mod4 = Super_L +! add control = Super_L diff --git a/configs/shared/x_server/.Xresources b/configs/shared/x_server/.Xresources new file mode 100644 index 000000000000..f29eb2945110 --- /dev/null +++ b/configs/shared/x_server/.Xresources @@ -0,0 +1,2 @@ +! value for laptop +Xft.dpi: 200 diff --git a/configs/shared/x_server/.xsessionrc b/configs/shared/x_server/.xsessionrc new file mode 100644 index 000000000000..062293bf5a47 --- /dev/null +++ b/configs/shared/x_server/.xsessionrc @@ -0,0 +1,28 @@ +#!/bin/sh + +source ~/.profile + +export DESKTOP_SESSION=cinnamon # gnome for trusty. + +# NOTE: This may break your compose key. +# See http://g/i3-users/YBexXGbik7E for more details. +export GTK_IM_MODULE=xim + +# Desktop background color. +xsetroot -solid "#333333" + +# start the urxvt daemon +urxvtd -q -f -o + +# set kbds +xmodmap -e 'remove Lock = Caps_Lock' +xmodmap -e 'keysym Caps_Lock = Escape' + +# set key repeat preferences +xset r rate 250 60 + +# setup OSX style scrolling for gLinux Mouse +xinput --set-prop 'PixArt Lenovo USB Optical Mouse' 'libinput Natural Scrolling Enabled' 1 + +# increase mouse speed +xinput --set-prop 'PixArt Lenovo USB Optical Mouse' 'libinput Accel Speed' 1 diff --git a/configs/shared/zsh/.zshrc b/configs/shared/zsh/.zshrc index 721bc8c74cab..349e7cebf0df 100644 --- a/configs/shared/zsh/.zshrc +++ b/configs/shared/zsh/.zshrc @@ -5,8 +5,6 @@ antigen use oh-my-zsh # Bundles from robbyrussell's oh-my-zsh repo. antigen bundle git -antigen bundle alias-tips # friendly reminders to prefer an alias if exists -# antigen bundle common-aliases # be careful with the load order here. Can easily eclipse aliases undesirably antigen bundle extract # extracts archives polymorphically antigen bundle zsh-completions # extracts archives polymorphically @@ -16,19 +14,20 @@ antigen bundle zsh-users/zsh-syntax-highlighting # Theming # This supports different ZSH themes for each machine case "$(hostname)" in - wpcarro.c.googlers.com) antigen theme cloud;; - wpcarro.lon.corp.google.com) antigen theme frisk;; - *) antigen theme refined;; + # desktop + wpcarro.lon.corp.google.com) + antigen theme frisk;; + # cloudtop + wpcarro.c.googlers.com) + antigen theme cloud;; + # laptop + wpcarro.roam.googlers.com) + antigen theme refined;; esac # Leave this last antigen apply -# Personal Configuration - -# Set environment variables for Nix -source ~/.nix-profile/etc/profile.d/nix.sh - # Configure fzf source "$(fzf-share)/key-bindings.zsh" @@ -45,9 +44,7 @@ fi # Directories. zstyle ':completion:*' users root $USER -# use full path instead of $DOTFILES, since DOTFILES is set herein -DOTFILES="$HOME/programming/dotfiles" source "$DOTFILES/configs/shared/zsh/variables.zsh" source "$DOTFILES/configs/shared/zsh/aliases.zsh" source "$DOTFILES/configs/shared/zsh/functions.zsh" -source "$DOTFILES/configs/shared/zsh/dumping_grounds.zsh" +source "$DOTFILES/configs/shared/zsh/zle.zsh" diff --git a/configs/shared/zsh/aliases.zsh b/configs/shared/zsh/aliases.zsh index ad00763dad59..4322c861725a 100644 --- a/configs/shared/zsh/aliases.zsh +++ b/configs/shared/zsh/aliases.zsh @@ -1,11 +1,21 @@ # Applications -# dired: di -# docker: dk +# +# Supported qualifiers: +# hidden: h +# ignore-case: i +# +# Supported verbs: +# source: s +# install: i +# test: t +# build: b +# list: ls # Misc alias c="xclip -selection clipboard -i" alias p="xclip -selection clipboard -o" -alias md="mkdir_cd" +alias mdd="mkdir_cd" +alias mdp='mkdir --parents' alias ls="exa" alias ll="exa -l" alias la="exa -la" @@ -21,14 +31,21 @@ alias btctl=bluetoothctl alias rg='rg --ignore-case' alias rgh='rg --hidden' # By default, rg skips hidden files alias fdh='fd --hidden' # By default, rg skips hidden files +alias define=sdcv # uses stardict to lookup a word # Gnome alias na=nautilus # Gnome's graphical file browser. Useful to click and dragging files into emails +# Tmux +alias tls='tmux list-sessions' + # Chrome alias cssh='chrome --app-id=pnhechapfaindjhompbnflcldabbghjo' # Secure Shell alias crd='chrome --app-id=gbchcmhmhahfdphkhkmpfmihenigjmpp' # Chrome Remote Desktop +# Dropbox +alias drst='dropbox.py status' + # Docker alias dk="docker" alias dkps="docker ps" @@ -90,7 +107,7 @@ alias hgco='hg update' alias sb="stack build" alias se="stack exec --" alias sc="stack clean" -alias st="stack test" +# alias st="stack test" # blocks suckless-terminal alias haddocks='open "$(stack path --local-doc-root)/index.html"' # Kubernetes @@ -107,6 +124,12 @@ alias nq="nix_introspect" alias nsh="nix-shell" alias nshp="nix-shell --pure" alias nr="nix repl" +alias ni='nix-env --install' +alias nrm='nix-env --uninstall' +alias nls='nix-env --query' + +# Aptitude (apt) +alias apti='sudo apt-get install' # couple the e* aliases to the <leader>e* kbds in vim alias ev='e ~/.config/nvim/init.vim' @@ -117,6 +140,7 @@ alias ef='e ~/functions.zsh' alias el='e ~/variables.zsh' alias ex='e ~/.Xresources' alias ei='e ~/.config/i3/config' +alias em='e ~/.tmux.conf' # couple the s* aliases to the <leader>s* kbds in vim alias sz='source ~/.zshrc' @@ -125,6 +149,7 @@ alias sf='source ~/functions.zsh' alias sl='source ~/variables.zsh' alias sx='xrdb ~/.Xresources' alias si='i3-msg restart' +alias sm='tmux source-file ~/.tmux.conf' # Google aliases # blaze: bz @@ -138,5 +163,6 @@ alias br='borgcfg' alias pils='p4 listclients' alias pirm='p4 citc -d' alias pb=/google/src/head/depot/eng/tools/pastebin -alias pbc='p | pb --private --title $(date +${DATE_FMT})| tee >(c && chrome $(p))' # create a private gPaste from your clipboard's content; open the result in a browser +alias pbc='pb --private --title $(date +${date_fmt})| tee >(c && chrome $(p))' # create a private gPaste from your clipboard's content; open the result in a browser +alias pbcp='p | pb --private --title $(date +${date_fmt})| tee >(c && chrome $(p))' # create a private gPaste from your clipboard's content; open the result in a browser alias pbls='$BROWSER https://paste.googleplex.com/$(whoami)' diff --git a/configs/shared/zsh/dumping_grounds.zsh b/configs/shared/zsh/dumping_grounds.zsh deleted file mode 100644 index e61164fc64d1..000000000000 --- a/configs/shared/zsh/dumping_grounds.zsh +++ /dev/null @@ -1,433 +0,0 @@ -#!/usr/bin/env zsh - -# Docker -dsh() { - # Drop into a Docker shell. Shell defaults to /bin/bash. - container=$1 - cmd=${2-/bin/bash} - - docker exec -it "${container}" "${cmd}" -} - -# Emacs -dired() { - # Opens either the `$(pwd)` or `$1` in Emacs's `dired`. - # Uses i3 to focus Emacs. - directory=${1:-$(pwd)} - echo $directory - emacsclient --eval "(dired \"$directory\")" && focus Emacs -} - -org_capture() { - # Spawns an Emacs frame running org-capture. - echo called - emacsclient --create-frame \ - --frame-parameters '(quote (name . "org-protocol-capture"))' \ - --eval '(org-capture)' -} - -# Git -conflicts() { - # Edit git conflicts one-by-one in your favorite editor. - ${EDITOR} "$(git status --porcelain | awk '/^UU/ { print $2 }')" -} - -# GPG -gpg_encrypt() { - # Convenience function around encryping files and directories. - # Appends a .gpg extension and deletes the unencrypted source. - local file=${1} - - echo "Encrypting..." - - if [ -f "${file}" ]; then - gpg --symmetric "${file}" && \ - rm "${file}" - - elif [ -d "${file}" ]; then - tar -cz "${file}" | gpg --symmetric --output "${file}.tar.gz.gpg" - fi - - echo "Done." -} - -gpg_decrypt() { - # Convenience function around decrypting .gpg files and directories. - # Deletes the original encrypted file with the .gpg extension. - local file=$1 - - echo "Decrypting..." - - if [ -f "${file}" ]; then - gpg --decrypt "${file}" >"${file%.gpg}" && \ - rm "${file}" - - elif [ -d "${file}" ]; then - local outdir="${dirname%.tar.gz.gpg}" - - if [ -d "${outdir}" ]; then - echo "Output directory, ${outdir}, already exists and will be overwritten by this command. Aborting..." - return 1 - else - gpg --decrypt "${dirname}" | tar -xv - fi - fi - - echo "Done." -} - -# Python -python_sandbox() { - # Creates a nix-shell with the specified arguments as Python packages - nix-shell -p "python36.withPackages(p: with p; [$@])" -} - -# Haskell -cabal_unhell() { - # Run this function to save yourself from Cabal hell. - # Note: this will require that you reinstall packages for your projects again. - find ~/.ghc -maxdepth 1 -type d -exec rm -rf {} \; - rm -rf ~/.cabal/{lib,packages,share} -} - -haskell_sandbox() { - # Creates a nix-shell with the specified arguments as Haskell packages - nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [$@])" -} - -_haskell_test_watch_path() { - # Runs and watches the tests for a provided file path. - ghcid -c "stack ghci grid:lib grid:grid-test --ghci-options=-fobject-code" \ - --height="$(tput lines)" --width="$(tput cols)" --warnings --test "$1" -} - -_haskell_test_watch_pattern() { - # Runs and watches the tests that match a provided pattern. - stack test --file-watch grid:grid-test --ta "-p \"${1}\"" -} - -haskell_test_watch() { - # Accepts either a filepath or a pattern and runs a test-watcher for either. - if [ -f "$1" ]; then - _haskell_test_watch_path "$1" - else - _haskell_test_watch_pattern "$1" - fi -} - -# Kubernetes -kush() { - # Drop into a shell via Kubernetes. Shell defaults to /bin/bash. - local name=$1 - local cmd=${2-/bin/bash} - - kubectl exec -it "${name}" -- "${cmd}" -} - -# Misc -all_users() { - # Lists all of the known users in the Linux system - # Useful because when you type `~art` in a prompt and tab-complete, ZSH looks - # up all users whose names start with "art". It's also just interesting to - # have access to this information. - # - # NOTE: this is not as simple as `cat /etc/passwd` for reasons of which I'm - # not entirely sure. - getent passwd -} - -test_true_color() { - # Run this to test if your terminal emulator supports True Color - curl --silent https://raw.githubusercontent.com/JohnMorales/dotfiles/master/colors/24-bit-color.sh | bash -} - -path() { - # Pretty-print the $PATH variable - echo "$PATH" | tr : '\n' -} - -nix_installed() { - # Lists the packages installed with `nix-env` - nix-env -q -} - -nix_store() { - # Print the packages in /nix/store without the preceding hash - ls /nix/store | sed 's/[a-z0-9]*-//' -} - -browse() { - # Open a URL in $BROWSER. Friendly for terminal input and output. - nohup "$BROWSER" $@ & -} - -lh() { - # Opens http://localhost:<port> in your $BROWSER. - # Usage: `lh 8080` - # Here, in case it wasn't obvious, `lh` stands for "localhost". - browse "http://localhost:$1" -} - -essids() { - # Returns a list of all ESSIDs the network card detects - local interface=${1-wlp4s0} - sudo iwlist "${interface}" scan | awk -F \" '{print $2}' | sed '/^\s*$/d' -} - -mkdir_cd() { - # Make and cd into a directory or path - mkdir -p "$1" && cd "$1" -} - -swap() { - # Swaps the names of files and directories. - local file_a="${1}" - local file_b="${2}" - - if [ -d "${file_a}" ] && [ -d "${file_b}" ]; then - local backup=$(mktemp -d backup.XXX) - - mv "${file_a}" "${backup}" - mv "${file_b}" "${file_a}" - mv "${backup}/${file_a}" "${file_b}" - rm -rf "${backup}" - elif [ -f "${file_a}" ] && [ -f "${file_b}" ]; then - local backup=$(mktemp backup.XXX) - - mv "${file_a}" "${backup}" - mv "${file_b}" "${file_a}" - mv "${backup}" "${file_b}" - rm "${backup}" - fi - - echo "Swapped: ${file_a} <-> ${file_b}" -} - -bak() { - # Backup a file or a directory by appending a .bak extension to it. - mv "$1" "$1.bak" -} - -unbak() { - # Restore a file by removing the .bak extension from it. - mv "$1.bak" "$1" -} - -is_online() { - # Pings google.com and echos "Online" or "Offline" and returns the appropriate - # exit code. Could be useful in the ${PS1} variable. - wget -q --spider "http://google.com" - - if [ $? -eq 0 ]; then - echo "Online" - return 0 - else - echo "Offline" - return 1 - fi -} - -du_it_live() { - # Outputs and refreshes the size of a directory's content. - # Useful for watching a directory as large amounts of data are - # downloaded into it. - local directory="${1}" - - while true; do - du -hc "${directory}" | tail -n 1 | tr -d '\n' && echo -n ' ' && sleep 0.5 - - # elipsis - echo -n '.' && sleep 0.5 && - echo -n '.' && sleep 0.5 && - echo -n '.' && sleep 0.5 && - - # clear the three-dots - echo -n '\b\b\b' && echo -n ' ' && echo -n '\r' - done -} - -router() { - # Returns the IP address of the network's router. - # Useful in a call like `ping $(router)` to diagnose an internet problem. - netstat -nr | grep default | head -n 1 | awk '{ print $2 }' -} - -monitor_dimensions() { - # Outputs the dimensions of your computer monitor - xdpyinfo | awk '/dimensions/{ print $2 }' -} - -list_sinks() { - # Lists the available output sources (speakers?) - pacmd list-sinks | grep -e 'name:' -e 'index:' -} - -list_sources() { - # List available input sources (microphones?) - pacmd list-sources | grep -e 'index:' -e device.string -e 'name:' -} - -lt() { - # Convenience wrapper around `exa --tree`. - # Optionally accepts a number for the max-depth and a directory to list. - # $ lt 2 ./scripts - - # lt - if [ -z ${1} ]; then - exa --tree --all - - # lt 2 - elif [[ "${1}" =~ '^[0-9]+$' ]] && [ -z ${2} ]; then - local depth="${1}" - - exa --tree -all --level "${depth}" - - # lt ./scripts - elif [ -z ${2} ]; then - local directory="${1}" - - exa --tree --all "${directory}" - - # lt 2 ./scripts - else - local depth=${1} - local directory="${2}" - - exa --tree --all --level ${depth} "${directory}" - fi -} - -gql() { - # Convenience wrapper around `http POST` that allows you write GQL queries in - # Vim before posting them to the server. - local endpoint="${1}" - local query="/tmp/http-query.gql" - - vim "${query}" && \ - echo "{\"query\":\"$(cat ${query})\"}" | \ - http --body POST "${endpoint}" -} - -# Nix -nix_introspect() { - # Greps through my local nixpkgs repo for - rg --after-context 5 "\\b$1\\b\\s*=" "$(nix-instantiate --find-file nixpkgs)" -} - -# Tmux -t() { - # Find or create a Tmux session. - local session_name="${1}" - if ! tmux has-session -t "${session_name}" 2> /dev/null; then - local oldTMUX="${TMUX}" - unset TMUX - tmux new -d -s "${session_name}" -n "${session_name}" - export TMUX="${oldTMUX}" - unset oldTMUX - - if command -v j >/dev/null; then - tmux send-keys -t "${session_name}" "j ${session_name}; clear" "C-m" - else - tmux send-keys -t "${session_name}" - fi - fi - if [[ -n "${TMUX}" ]]; then - tmux switch-client -t "${session_name}" - else - tmux attach -t "${session_name}" - fi -} - -tk() { - # `tk`: "tmux kill". Kills a tmux session by name. - # If no arguments are provided, kills the current session after jumping to the previous session. - session_name="${1}" - if [ ! -z "${session_name}" ]; then - tmux kill-session -t "${session_name}" - else - session_name=tmux ls -f '#{?session_attached,#{session_name},}' | xargs - tmux switch-client -l - tmux kill-session -t "${session_name}" - fi -} - -tmux_is_running() { - # Returns zero if tmux is running - # Although this is a simple function body, it's useful to encode esoteric - # knowledge that I will easily forget. - test -n "$TMUX" -} - -tmux_focused_pane() { - # Returns the ID of the focused tmux pane. - # WIP - # tmux list-panes -F '#{pane_active} #{pane_tty}' | awk /1/{ print $1 } - echo 'Not implemented' -} - -# Google3 -g3_root() { - # Outputs the root of the CitC client in g3 - # NOTE: there is probably a function already supported by g4 to cd to the - # root, so support for this function may be dropped shortly. - echo "${PWD%%/google3/*}/google3" -} - -# i3 -focus() { - # Focuses an i3 window by application name. - i3-msg "[class=\"$1\"] focus" >/dev/null -} - -# zsh -fns() { - # Outputs all available functions. - # `fns` was chosen instead of `functions`, since `functions` was already - # taken. - compgen -A function -} - -aliases() { - # Outputs all available aliases. - compgen -a -} - -keywords() { - # Outputs all of the shell's reserved keywords. - compgen -k -} - -builtins() { - # Outputs all of the shell's builtin commands. - compgen -b -} - -zle_insert_subshell() { - LBUFFER+='$(' ; RBUFFER=")$RBUFFER" -} -zle -N zle_insert_subshell -bindkey '^j' zle_insert_subshell - -zle_insert_variable() { - LBUFFER+='${' ; RBUFFER="}$RBUFFER" -} -zle -N zle_insert_variable -bindkey '^v' zle_insert_variable - -zle_insert_2x_dash() { - LBUFFER+=' --' -} -zle -N zle_insert_2x_dash -bindkey '^[^f' zle_insert_2x_dash - -zle_insert_2x_quote() { - LBUFFER+=' "' ; RBUFFER="\"$RBUFFER" -} -zle -N zle_insert_2x_quote -bindkey '^["' zle_insert_2x_quote - -zle_insert_quote() { - LBUFFER+=" '" ; RBUFFER="'$RBUFFER" -} -zle -N zle_insert_quote -bindkey "^['" zle_insert_quote diff --git a/configs/shared/zsh/functions.zsh b/configs/shared/zsh/functions.zsh index 12825102ae95..f555ae4e9aa2 100644 --- a/configs/shared/zsh/functions.zsh +++ b/configs/shared/zsh/functions.zsh @@ -1,14 +1,3 @@ -# From Google's ZSH Hacks -# NOTE: this file has since been modified by me. - -# Improvement to fasd's existing `zz` alias -unalias zz -zz() { - # TODO: Add documentation - local dir - dir="$(fasd -Rdl "$1" | fzf --query="$1" -1 -0 --no-sort +m)" && cd "${dir}" || return 1 -} - fv() { # Usage: fv file pattern # This is useful when you know the fuzzy name of the file you want to edit @@ -35,3 +24,540 @@ tj() { cd "${PWD/\/google3\/java//google3/javatests}" fi } + +snipit() { + # Take a screenshot and host it at https://screenshot.googleplex.com + # Adapted from SnipIt to fit my workflow. + server="https://screenshot.googleplex.com/upload" + file="${TEMP:-/tmp}/snipit_temp_$$.png" + + # Capture + echo "SnipIt - Click a window, or drag to snip a region (Ctrl+C to cancel):" && \ + import "$file" && \ + echo "Sending image to server..." && \ + uri=$(curl -sF "imagedata=@$file" $server) && \ + c <<<"$uri" && \ + echo "Copied \"$uri\" to your clipboard." +} + +# Aptitude +apts() { + # Searches aptitude package repository for $1, surrounding it in ^$ to ensure + # fewer results. + apt search "^$1$" +} + +# Docker +dsh() { + # Drop into a Docker shell. Shell defaults to /bin/bash. + container=$1 + cmd=${2-/bin/bash} + + docker exec -it "${container}" "${cmd}" +} + +# Emacs +dired() { + # Opens either the `$(pwd)` or `$1` in Emacs's `dired`. + # Uses i3 to focus Emacs. + directory=${1:-$(pwd)} + echo $directory + emacsclient --eval "(dired \"$directory\")" && focus Emacs +} + +org_capture() { + # Spawns an Emacs frame running org-capture. + echo called + emacsclient --create-frame \ + --frame-parameters '(quote (name . "org-protocol-capture"))' \ + --eval '(org-capture)' +} + +# Git +conflicts() { + # Edit git conflicts one-by-one in your favorite editor. + ${EDITOR} "$(git status --porcelain | awk '/^UU/ { print $2 }')" +} + +# GPG +gpg_encrypt() { + # Convenience function around encryping files and directories. + # Appends a .gpg extension and deletes the unencrypted source. + local file=${1} + + echo "Encrypting..." + + if [ -f "${file}" ]; then + gpg --symmetric "${file}" && \ + rm "${file}" + + elif [ -d "${file}" ]; then + tar -cz "${file}" | gpg --symmetric --output "${file}.tar.gz.gpg" + fi + + echo "Done." +} + +gpg_decrypt() { + # Convenience function around decrypting .gpg files and directories. + # Deletes the original encrypted file with the .gpg extension. + local file=$1 + + echo "Decrypting..." + + if [ -f "${file}" ]; then + gpg --decrypt "${file}" >"${file%.gpg}" && \ + rm "${file}" + + elif [ -d "${file}" ]; then + local outdir="${dirname%.tar.gz.gpg}" + + if [ -d "${outdir}" ]; then + echo "Output directory, ${outdir}, already exists and will be overwritten by this command. Aborting..." + return 1 + else + gpg --decrypt "${dirname}" | tar -xv + fi + fi + + echo "Done." +} + +# Python +python_sandbox() { + # Creates a nix-shell with the specified arguments as Python packages + nix-shell -p "python36.withPackages(p: with p; [$@])" +} + +# Haskell +cabal_unhell() { + # Run this function to save yourself from Cabal hell. + # Note: this will require that you reinstall packages for your projects again. + find ~/.ghc -maxdepth 1 -type d -exec rm -rf {} \; + rm -rf ~/.cabal/{lib,packages,share} +} + +haskell_sandbox() { + # Creates a nix-shell with the specified arguments as Haskell packages + nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [$@])" +} + +_haskell_test_watch_path() { + # Runs and watches the tests for a provided file path. + ghcid -c "stack ghci grid:lib grid:grid-test --ghci-options=-fobject-code" \ + --height="$(tput lines)" --width="$(tput cols)" --warnings --test "$1" +} + +_haskell_test_watch_pattern() { + # Runs and watches the tests that match a provided pattern. + stack test --file-watch grid:grid-test --ta "-p \"${1}\"" +} + +haskell_test_watch() { + # Accepts either a filepath or a pattern and runs a test-watcher for either. + if [ -f "$1" ]; then + _haskell_test_watch_path "$1" + else + _haskell_test_watch_pattern "$1" + fi +} + +# Kubernetes +kush() { + # Drop into a shell via Kubernetes. Shell defaults to /bin/bash. + local name=$1 + local cmd=${2-/bin/bash} + + kubectl exec -it "${name}" -- "${cmd}" +} + +# Misc +tldr_docs() { + # Helper function for submitting a new page to `tldr`. + # Usage: tldr_docs <cmd-name> + pushd ~/programming/tldr && \ + gcb "$1" && \ + "$EDITOR" . && \ + echo "Next steps:" && \ + echo "- commit changes" && \ + echo "- push changes" && \ + echo "- submit a pull-request to tldr" && \ + popd # return to the original directory +} + +ord_to_char() { + # Converts the ordinal, ASCII value of a character into its encoded + # representation. + # + # Usage: + # $ ord_to_char 65 + # A + [ "$1" -lt 256 ] || return 1 + printf "\\$(printf '%03o' "$1")\n" +} + +char_to_ord() { + # Converts the ASCII representation of a character to its ordinal value. + # + # Usage: + # $ char_to_ord A + # 65 + LC_CTYPE=C printf '%d\n' "'$1" +} + +all_users() { + # Lists all of the known users in the Linux system + # Useful because when you type `~art` in a prompt and tab-complete, ZSH looks + # up all users whose names start with "art". It's also just interesting to + # have access to this information. + # + # NOTE: this is not as simple as `cat /etc/passwd` for reasons of which I'm + # not entirely sure. + getent passwd +} + +escape_sequences() { + # Outputs a table of terminal escape sequences and their meaning. + echo -E '\a Bell (alert)' + echo -E '\b Backspace' + echo -E '\f Formfeed' + echo -E '\n New line' + echo -E '\r Carriage return' + echo -E '\t Horizontal tab' + echo -E '\v Vertical tab' + echo -E "\' Single quotation mark" + echo -E '\" Double quotation mark' + echo -E '\\ Backslash' + echo -E '\? Literal question mark' + echo -E '\uhhhh Unicode character' + echo -E '\Uhhhhhhhh Unicode character' + echo -E '\xhh ASCII character in hexadecimal notation' + echo -E '\xhhhh Unicode character in hexadecimal notation if this escape sequence is used in a wide-character constant or a Unicode string literal.' +} + +test_true_color() { + # Run this to test if your terminal emulator supports True Color + curl --silent https://raw.githubusercontent.com/JohnMorales/dotfiles/master/colors/24-bit-color.sh | bash +} + +test_16_colors() { + # Useful for testing your terminal's theme. + echo -e "Normal: ${black}black${red}red${green}green${yellow}yellow${blue}blue${magenta}magenta${cyan}cyan${white}white" + echo -e "Bright: ${bright_black}black${bright_red}red${bright_green}green${bright_yellow}yellow${bright_blue}blue${bright_magenta}magenta${bright_cyan}cyan${bright_white}white" +} + +test_text_formatting() { + # Useful when appraising a Tmux. Things can get strange with true colors and + # font rendering. + echo -e "\e[1mbold\e[0m" + echo -e "\e[3mitalic\e[0m" + echo -e "\e[4munderline\e[0m" + echo -e "\e[9mstrikethrough\e[0m" +} + +test_unicode() { + # Run this to test if your terminal supports unicode character rendering. + echo -e '\u2600 \u2601 \u2602 \u2603 \u2604 \u2605 \u2606 \u2607 \u2608 \u2609 \u260A' + echo -e '\u260B \u260C \u260D \u260E \u260F \u2610 \u2611 \u2612 \u2613 \u2614 \u2615' + echo -e '\u2616 \u2617 \u2618 \u2619 \u261A \u261B \u261C \u261D \u261E \u261F \u2620' + echo -e '\u2621 \u2622 \u2623 \u2624 \u2625 \u2626 \u2627 \u2628 \u2629 \u262A \u262B' + echo -e '\u262C \u262D \u262E \u262F \u2630 \u2631 \u2632 \u2633 \u2634 \u2635 \u2636' + echo -e '\u2637 \u2638 \u2639 \u263A \u263B \u263C \u263D \u263E \u263F \u2640 \u2641' + echo -e '\u2642 \u2643 \u2644 \u2645 \u2646 \u2647 \u2648 \u2649 \u264A \u264B \u264C' + echo -e '\u264D \u264E \u264F \u2650 \u2651 \u2652 \u2653 \u2654 \u2655 \u2656 \u2657' + echo -e '\u2658 \u2659 \u265A \u265B \u265C \u265D \u265E \u265F \u2660 \u2661 \u2662' + echo -e '\u2663 \u2664 \u2665 \u2666 \u2667 \u2668 \u2669 \u266A \u266B \u266C \u266D' + echo -e '\u266E \u266F \u2670 \u2671 \u2672 \u2673 \u2674 \u2675 \u2676 \u2677 \u2678' + echo -e '\u2679 \u267A \u267B \u267C \u267D \u267E \u267F \u2680 \u2681 \u2682 \u2683' + echo -e '\u2684 \u2685 \u2686 \u2687 \u2688 \u2689 \u268A \u268B \u268C \u268D \u268E' + echo -e '\u268F \u2690 \u2691 \u2692 \u2693 \u2694 \u2695 \u2696 \u2697 \u2698 \u2699' + echo -e '\u269A \u269B \u269C \u269D \u269E \u269F \u26A0 \u26A1 \u26A2 \u26A3 \u26A4' + echo -e '\u26A5 \u26A6 \u26A7 \u26A8 \u26A9 \u26AA \u26AB \u26AC \u26AD \u26AE \u26AF' + echo -e '\u26B0 \u26B1 \u26B2 \u26B3 \u26B4 \u26B5 \u26B6 \u26B7 \u26B8 \u26B9 \u26BA' + echo -e '\u26BB \u26BC \u26BD \u26BE \u26BF \u26C0 \u26C1 \u26C2 \u26C3 \u26C4 \u26C5' + echo -e '\u26C6 \u26C7 \u26C8 \u26C9 \u26CA \u26CB \u26CC \u26CD \u26CE \u26CF \u26D0' + echo -e '\u26D1 \u26D2 \u26D3 \u26D4 \u26D5 \u26D6 \u26D7 \u26D8 \u26D9 \u26DA \u26DB' + echo -e '\u26DC \u26DD \u26DE \u26DF \u26E0 \u26E1 \u26E2 \u26E3 \u26E4 \u26E5 \u26E6' + echo -e '\u26E7 \u26E8 \u26E9 \u26EA \u26EB \u26EC \u26ED \u26EE \u26EF \u26F0 \u26F1' + echo -e '\u26F2 \u26F3 \u26F4 \u26F5 \u26F6 \u26F7 \u26F8 \u26F9 \u26FA \u26FB \u26FC' + echo -e '\u26FD \u26FE \u26FF' +} + +path() { + # Pretty-print the $PATH variable + echo "$PATH" | tr : '\n' +} + +nix_installed() { + # Lists the packages installed with `nix-env` + nix-env -q +} + +nix_store() { + # Print the packages in /nix/store without the preceding hash + ls /nix/store | sed 's/[a-z0-9]*-//' +} + +browse() { + # Open a URL in $BROWSER. Friendly for terminal input and output. + nohup "$BROWSER" $@ & +} + +lh() { + # Opens http://localhost:<port> in your $BROWSER. + # Usage: `lh 8080` + # Here, in case it wasn't obvious, `lh` stands for "localhost". + browse "http://localhost:$1" +} + +essids() { + # Returns a list of all ESSIDs the network card detects + local interface=${1-wlp4s0} + sudo iwlist "${interface}" scan | awk -F \" '{print $2}' | sed '/^\s*$/d' +} + +mkdir_cd() { + # Make and cd into a directory or path + mkdir -p "$1" && cd "$1" +} + +swap() { + # Swaps the names of files and directories. + local file_a="${1}" + local file_b="${2}" + + if [ -d "${file_a}" ] && [ -d "${file_b}" ]; then + local backup=$(mktemp -d backup.XXX) + + mv "${file_a}" "${backup}" + mv "${file_b}" "${file_a}" + mv "${backup}/${file_a}" "${file_b}" + rm -rf "${backup}" + elif [ -f "${file_a}" ] && [ -f "${file_b}" ]; then + local backup=$(mktemp backup.XXX) + + mv "${file_a}" "${backup}" + mv "${file_b}" "${file_a}" + mv "${backup}" "${file_b}" + rm "${backup}" + fi + + echo "Swapped: ${file_a} <-> ${file_b}" +} + +bak() { + # Backup a file or a directory by appending a .bak extension to it. + mv "$1" "$1.bak" +} + +unbak() { + # Restore a file by removing the .bak extension from it. + mv "$1.bak" "$1" +} + +is_online() { + # Pings google.com and echos "Online" or "Offline" and returns the appropriate + # exit code. Could be useful in the ${PS1} variable. + wget -q --spider "http://google.com" + + if [ $? -eq 0 ]; then + echo "Online" + return 0 + else + echo "Offline" + return 1 + fi +} + +du_it_live() { + # Outputs and refreshes the size of a directory's content. + # Useful for watching a directory as large amounts of data are + # downloaded into it. + local directory="${1}" + + while true; do + du -hc "${directory}" | tail -n 1 | tr -d '\n' && echo -n ' ' && sleep 0.5 + + # elipsis + echo -n '.' && sleep 0.5 && + echo -n '.' && sleep 0.5 && + echo -n '.' && sleep 0.5 && + + # clear the three-dots + echo -n '\b\b\b' && echo -n ' ' && echo -n '\r' + done +} + +router() { + # Returns the IP address of the network's router. + # Useful in a call like `ping $(router)` to diagnose an internet problem. + netstat -nr | grep default | head -n 1 | awk '{ print $2 }' +} + +monitor_dimensions() { + # Outputs the dimensions of your computer monitor + xdpyinfo | awk '/dimensions/{ print $2 }' +} + +list_sinks() { + # Lists the available output sources (speakers?) + pacmd list-sinks | grep -e 'name:' -e 'index:' +} + +list_sources() { + # List available input sources (microphones?) + pacmd list-sources | grep -e 'index:' -e device.string -e 'name:' +} + +lt() { + # Convenience wrapper around `exa --tree`. + # Optionally accepts a number for the max-depth and a directory to list. + # $ lt 2 ./scripts + + # lt + if [ -z ${1} ]; then + exa --tree --all + + # lt 2 + elif [[ "${1}" =~ '^[0-9]+$' ]] && [ -z ${2} ]; then + local depth="${1}" + + exa --tree -all --level "${depth}" + + # lt ./scripts + elif [ -z ${2} ]; then + local directory="${1}" + + exa --tree --all "${directory}" + + # lt 2 ./scripts + else + local depth=${1} + local directory="${2}" + + exa --tree --all --level ${depth} "${directory}" + fi +} + +gql() { + # Convenience wrapper around `http POST` that allows you write GQL queries in + # Vim before posting them to the server. + local endpoint="${1}" + local query="/tmp/http-query.gql" + + vim "${query}" && \ + echo "{\"query\":\"$(cat ${query})\"}" | \ + http --body POST "${endpoint}" +} + +# Nix +nix_introspect() { + # Greps through my local nixpkgs repo for + rg --after-context 5 "\\b$1\\b\\s*=" "$(nix-instantiate --find-file nixpkgs)" +} + +# Tmux +t() { + # Find or create a Tmux session. + local session_name="${1}" + if ! tmux has-session -t "${session_name}" 2> /dev/null; then + local oldTMUX="${TMUX}" + unset TMUX + tmux new -d -s "${session_name}" -n "${session_name}" + export TMUX="${oldTMUX}" + unset oldTMUX + + if command -v j >/dev/null; then + tmux send-keys -t "${session_name}" "j ${session_name}; clear" "C-m" + else + tmux send-keys -t "${session_name}" + fi + fi + if [[ -n "${TMUX}" ]]; then + tmux switch-client -t "${session_name}" + else + tmux attach -t "${session_name}" + fi +} + +tk() { + # `tk`: "tmux kill". Kills a tmux session by name. + # If no arguments are provided, kills the current session after jumping to the previous session. + session_name="${1}" + if [ ! -z "${session_name}" ]; then + tmux kill-session -t "${session_name}" + else + session_name=tmux ls -f '#{?session_attached,#{session_name},}' | xargs + tmux switch-client -l + tmux kill-session -t "${session_name}" + fi +} + +tmux_is_running() { + # Returns zero if tmux is running + # Although this is a simple function body, it's useful to encode esoteric + # knowledge that I will easily forget. + test -n "$TMUX" +} + +tmux_focused_pane() { + # Returns the ID of the focused tmux pane. + # WIP + # tmux list-panes -F '#{pane_active} #{pane_tty}' | awk /1/{ print $1 } + echo 'Not implemented' +} + +# Google3 +g3_root() { + # Outputs the root of the CitC client in g3 + # NOTE: there is probably a function already supported by g4 to cd to the + # root, so support for this function may be dropped shortly. + echo "${PWD%%/google3/*}/google3" +} + +citc_workspace() { + # Returns the name of your current CitC workspace + pwd | grep -o -P "$(whoami)\/[^\/]+" +} + +codesearch() { + # Attempts to open the current directory in Google's Code Search. + local slug="$(pwd | grep -P -o 'google3\/.+$')" + browse "https://cs.corp.google.com/piper///depot/$slug" +} + +cider() { + # Opens the current workspace and current directory in Google's Cider + # Not very useful at the moment because it cannot jump to the current file or + # line number. Should also support an Emacs integration at some point. + browse "https://cider.corp.google.com/?ws=$(citc_workspace)" +} + +# i3 +focus() { + # Focuses an i3 window by application name. + i3-msg "[class=\"$1\"] focus" >/dev/null +} + +# zsh +fns() { + # Outputs all available functions. + # `fns` was chosen instead of `functions`, since `functions` was already + # taken. + compgen -A function +} + +aliases() { + # Outputs all available aliases. + compgen -a +} + +keywords() { + # Outputs all of the shell's reserved keywords. + compgen -k +} + +builtins() { + # Outputs all of the shell's builtin commands. + compgen -b +} diff --git a/configs/shared/zsh/variables.zsh b/configs/shared/zsh/variables.zsh index 5e8e67ed0221..40611805ad8a 100644 --- a/configs/shared/zsh/variables.zsh +++ b/configs/shared/zsh/variables.zsh @@ -1,20 +1,19 @@ -export TERMINAL=urxvtc -export EDITOR=emacsclient -export ALTERNATE_EDITOR=nvim export GPG_TTY=$(tty) # "It is important that this environment variable always reflects the output of the tty command". Source: https://gnupg.org/documentation/manuals/gnupg-devel/Invoking-GPG_002dAGENT.html -BROWSER=google-chrome -NIXIFY="$HOME/programming/nixify" -DATE_FMT=%b-%d-%Y_%T # my preferred date formatting string used for generated filename +date_fmt=%b-%d-%Y_%T # my preferred date formatting string used for generated filename # ZSH's static named directories hash -d pro=~/programming -hash -d dot=~/programming/dotfiles +hash -d dot="$DOTFILES" hash -d citc=/google/src/cloud/$USER hash -d doc=~/Documents hash -d d=~/Downloads hash -d ss=~/Pictures/screenshots -hash -d org=~/Documents/org +hash -d fonts="$DOTFILES/configs/linux/misc/.local/share/fonts" +hash -d sounds="$DOTFILES/configs/linux/misc/.local/share/sounds" +hash -d wallpaper="$DOTFILES/configs/linux/misc/.local/share/wallpaper" +hash -d org="$ORG_DIRECTORY" +hash -d x20=/google/data/rw/users/wp/wpcarro # remember: to access x20, you need to run `prodaccess` # named directories for commonly used projects hash -d korvus_framework=./java/com/google/corp/sales hash -d korvus_services=./corp/sales/casesautomation @@ -23,6 +22,24 @@ hash -d ultra=./ads/doubleclick/systems/crm hash -d incentives_fe=./experimental/adservices/jarvis/jarvis_extension/jarvis_staging/js hash -d incentives_be=./experimental/adservices/tesseract/handlers/incentives +# 8-bit colors +black='\u001b[30m' +red='\u001b[31m' +green='\u001b[32m' +yellow='\u001b[33m' +blue='\u001b[34m' +magenta='\u001b[35m' +cyan='\u001b[36m' +white='\u001b[37m' +bright_black='\u001b[30;1m' +bright_red='\u001b[31;1m' +bright_green='\u001b[32;1m' +bright_yellow='\u001b[33;1m' +bright_blue='\u001b[34;1m' +bright_magenta='\u001b[35;1m' +bright_cyan='\u001b[36;1m' +bright_white='\u001b[37;1m' + # commonly used config files v="$HOME/.config/nvim/init.vim" e="$HOME/.emacs.d/init.el" diff --git a/configs/shared/zsh/zle.zsh b/configs/shared/zsh/zle.zsh new file mode 100644 index 000000000000..4ded511ffccf --- /dev/null +++ b/configs/shared/zsh/zle.zsh @@ -0,0 +1,31 @@ +#!/usr/bin/env zsh + +zle_insert_subshell() { + LBUFFER+='$(' ; RBUFFER=")$RBUFFER" +} +zle -N zle_insert_subshell +bindkey '^j' zle_insert_subshell + +zle_insert_variable() { + LBUFFER+='${' ; RBUFFER="}$RBUFFER" +} +zle -N zle_insert_variable +bindkey '^v' zle_insert_variable + +zle_insert_2x_dash() { + LBUFFER+=' --' +} +zle -N zle_insert_2x_dash +bindkey '^[^f' zle_insert_2x_dash + +zle_insert_2x_quote() { + LBUFFER+=' "' ; RBUFFER="\"$RBUFFER" +} +zle -N zle_insert_2x_quote +bindkey '^["' zle_insert_2x_quote + +zle_insert_quote() { + LBUFFER+=" '" ; RBUFFER="'$RBUFFER" +} +zle -N zle_insert_quote +bindkey "^['" zle_insert_quote |