I53WDJDV6QGJYSZK3NLHLNDJHZ5F4UQ4LWVKCN42NUMQ7ABFYD3AC if [ -z "$DISPLAY" ] && [ -n "$XDG_VTNR" ] && [ "$XDG_VTNR" -eq 1 ]; thenexec startxfi[ -z "$PS1" ] && return. .bashrcif [[ $TERM == xterm-termite ]]; then. /etc/profile.d/vte.sh__vte_prompt_commandfiexport PATH="$HOME/.local/bin:$PATH"#source /home/zero/.config/broot/launcher/bash/brexport PATH=/usr/local/node-v20.15.1/bin:$PATH. "$HOME/.cargo/env"
*VT100*colorMode: on*VT100*dynamicColors: onXft.antialias: trueXft.hinting: trueXft.hintstyle: hintslightXft.rgba: rgbXft.dpi: 96! special*.foreground: #d0d0d0*.background: #222222*.cursorColor: #79d4d5! black*.color0: #191919*.color8: #747369! red*.color1: #f2777a*.color9: #913535! green*.color2: #99cc99*.color10: #A0A35D! yellow*.color3: #ffcc66*.color11: #C47848! blue*.color4: #6699cc*.color12: #527386! magenta*.color5: #cc99cc*.color13: #846488! cyan*.color6: #66cccc*.color14: #618E8B! white*.color7: #ffffff*.color15: #969896*.selection_background: #79d4d5*.selection_foreground: #000000Xcursor.size: 22!xtermXTerm.termName: xterm-256colorXTerm*utf8: 1!XTerm*faceName: Source Code Pro - BlackXTerm*faceName: SauceCodePro Nerd Font MonoXTerm*metaSendsEscape: trueXTerm*faceSize: 7XTerm*cursor: i-beamXTerm*visualBell: falseXTerm*cursorColor: #79d4d5XTerm*cursorBlink: trueXTerm*toolBar: falseXTerm*internalBorder: 20XTerm*borderWidth: 0XTerm*loginShell: trueXTerm*scrollBar: falseXTerm*rightScrollBar: falseXTerm*saveLines: 999!XTerm*selectToClipboard: true! enable OSC 52 clipboard supportXTerm.vt100.allowWindowOps: trueXTerm.vt100.disallowedWindowOps: 20,21,SetXprop!XTerm.vt100.selectToClipboard: true! urxvtURxvt*internalBorder: 20URxvt*buffered: trueURxvt*jumpScroll: trueURxvt*skipScroll: trueURxvt*visualBell: falseURxvt*cursorColor: #79d4d5URxvt*cursorBlink: trueURxvt.underlineURLs: falseURxvt*font: xft:Source Code Pro - Black:size=7URxvt.letterSpace: -1URxvt.lineSpace: 0URxvt*depth: 32URxvt*borderless: trueURxvt*scrollBar: falseURxvt*loginShell: trueURxvt*secondaryScroll: true # Enable Shift-PageUp/Down in screenURxvt*saveLines: 5000URxvt*termName: rxvt-unicode-256colorURxvt.keysym.Shift-Control-V: eval:paste_clipboardURxvt.keysym.Shift-Control-C: eval:selection_to_clipboardURxvt.iso14755: falseURxvt.iso14755_52: false! xstst.borderless: 1st.font: Source Code Pro:pixelsize=9:antialias=true:autohint=true;st.borderpx: 20st.cursorblinkontype: 0st.blinktimeout: 300
" pluginspackloadall"syntaxsyntax on" indentationfiletype plugin indent on"set titleset tabstop=3set shiftwidth=3set expandtabset autoindentset smartindentset smarttabset shm=filmnwxosTIc" cursorset guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20set guicursor+=v:hor20-CursorVisualset laststatus=2"set statusline=%<%F\ %h%m%r%y%=%-14.(%l,%c%V%)\ %P" no modelineset noml" no show modeset nosmd" no rulerset noru" searchesset gdefaultset hlsearchset incsearchset nowrapscanset ignorecaseset smartcase " search is case sensitive iff contain uppercase charsset path+=** " recursive search with :find (provides tab completion for all file related searches)set mmp=200000 " maxmempattern" persistent undoset undofile " Save undos after file closesset undodir=$HOME/.vim/undo " where to save undo historiesset undolevels=1000 " How many undosset undoreload=10000 " number of lines to save for undo" miscset shm+=Fsset t_Co=16 " nvim lua sets this to 256set t_u7=set swapfileset writebackupset nobackupset directory=$HOME/.vim/swapfiles//set updatetime=750set showcmdset encoding=utf-8set showmatchset linebreakset scrolloff=7set nowrapset foldmethod=indentset foldnestmax=1set foldminlines=1set foldlevel=1set foldtext=set fillchars+=vert:\|"set cmdheight=0 " hide cmdline but get Hit Enter prompts" hidden charactersset listset listchars=tab:·\ ,trail:·" wildset wildmode=longest:full,fullset wildmenu" exclude newline from v$set selection=old" sign columnset scl=yes" abs + rel line numbersset nu rnu" cursor lineset cul" cul_togglefunction CulOn()augroup cul_toggleau!au InsertEnter,WinLeave,FocusLost * setl noculau InsertLeave,WinEnter,FocusGained * setl culaugroup endset culendfunctionfunction CulOff()au! cul_toggleaugroup! cul_toggleset noculendfunctionfunction CulToggle()if exists('#cul_toggle'):silent! call CulOff()else:silent! call CulOn()endifendfunctionsilent! call CulOn()command Cul call CulToggle()nnoremap <leader>C :Cul<cr>" signcolumn togglennoremap <leader>D :let currwin=win_getid() \| windo execute 'setlocal signcolumn=' . (&signcolumn ==# 'no' ? 'auto' : 'no') \| call win_gotoid(currwin) \| redraw! \| echon (&signcolumn ==# 'no' ? 'diffs off' : 'diffs on')<CR>" numbers_togglefunction NumbersOn()augroup numbers_toggleau!au insertleave,winenter,focusgained * if &buftype !=# 'terminal' | setl nu rnu | endifau insertenter,winleave,focuslost * if &buftype !=# 'terminal' | setl nu nornu | endifaugroup endwindo set nu rnuecho "numbers on"endfunctionfunction NumbersOff()au! numbers_toggleaugroup! numbers_togglewindo set nonu nornuecho "numbers off"endfunctionfunction NumbersToggle()let currwin=win_getid()if exists('#numbers_toggle'):silent! call NumbersOff()else:silent! call NumbersOn()endifcall win_gotoid(currwin)endfunctionsilent! call NumbersOff()command Numbers call NumbersToggle()nnoremap <leader>N :Numbers<cr>" if exists('##TermOpen')" au TermOpen * setl nonu nornu" au TermOpen * setl scrolloff=0" au TermEnter * match IncSearch """ endif" " hide line numbers on Terminal Insert mode" if exists('##TermOpen')" au TermOpen * setl scrolloff=0" au TermOpen * setl nu rnu" au TermEnter * match IncSearch """ au TermEnter * setl nonu nornu" au TermLeave * setl nu rnu" endif" " start :term in insert mode : causes trouble" if exists('##TermOpen')" au TermOpen * startinsert" endif" terminal normal mode window command on ^wtnoremap <C-w> <C-\><C-n><C-w>"tnoremap <esc><esc> <C-\><C-n><C-w><esc>" vertical shift variations of default commandsnnoremap <C-w>N :vnew<cr>nnoremap <C-w>S :vsplit<cr>" open a new terminal windownnoremap <C-w>t :horizontal :terminal<cr>nnoremap <C-w>T :vertical :terminal<cr>nnoremap <C-w><cr> :horizontal :terminal<cr>nnoremap <C-w><S-cr> :vertical :terminal<cr>" ^w w goes to previousnnoremap <C-w>w <C-w>pnnoremap <C-w><C-w> <C-w>p" go to previous buffernnoremap <leader><tab> :b#<cr>" infer suffixes on gf, ...set sua=.js,.hs,.rs,.py,.nim,.go" auto :noh" (remapping ESC causes weird behaviour)nnoremap <leader><space> :noh<cr>nnoremap <leader><esc> :noh<cr>nnoremap <esc> :noh<cr>" hilight current wordnnoremap <leader><leader> #*" global substitutennoremap <leader>s :%s/" global substitute current selectionvnoremap <leader>s y:%s/<C-r>"/" hilight current selectionvnoremap <cr> y/<C-r>"<cr>gv<esc>" disable auto commentau FileType * set formatoptions-=cro" neovim: incremental :sif exists('+inccommand')set inccommand=nosplitendif" default cursorslet &t_SI = "\e[6 q"let &t_SR = "\e[4 q"let &t_EI = "\e[2 q"" change cursor to pipe in insert mode"au InsertEnter * silent exe "!echo -en \<esc>[6 q""au InsertLeave * silent exe "!echo -en \<esc>[2 q"" block cursor on open" au VimEnter * silent exe "!echo -en \<esc>[2 q"" dont display the bannerlet g:netrw_banner=0" start netrw in tree view (iterate: i)let g:netrw_liststyle=3" hide dot files on start"let g:netrw_list_hide='\(^\|\s\s\)\zs\.\s\+'let g:netrw_list_hide='^\..*'let g:netrw_hide=0" auto-size netrw windowlet g:netrw_winsize= 16" close unmodified buffersau FileType netrw setl bufhidden=delete "or use :qa!" Y yanks until the end of linennoremap Y y$" go to marked columnsnnoremap ' `nnoremap ` '" " vimgrep current word" nnoremap gK :exe 'lvimgrep /\<'.expand('<cword>').'\>\C/j **/*.'.expand('%:e').' \| lw'<cr>" vnoremap gK "vy:lvimgrep /\V<C-r>v/j **/* \| lw<cr>" gp, gP pastes from "0nnoremap <leader>p "0pnnoremap <leader>P "0Pvnoremap <leader>p "0pvnoremap <leader>P "0P" put delimiters around selectionvnoremap ( c()<esc>Pgvo<esc>vnoremap ) c(<esc>pa)<esc>vnoremap g( c( <esc>pa )<esc>'[vnoremap g) c( <esc>pa )<esc>" vnoremap " <C-v>c""<esc>P% " prevents yanking to registervnoremap [ c[]<esc>Pgvo<esc>vnoremap g[ c[ <esc>pa ]<esc>'[vnoremap ] c[]<esc>P<esc>vnoremap g] c[ <esc>pa ]<esc>"vnoremap { c{}<esc>Pgvo<esc>"vnoremap g{ c{ <esc>pa }<esc>'["vnoremap } c{}<esc>P<esc>"vnoremap g} c{ <esc>pa }<esc>vnoremap < <gvvnoremap > >gv" move selection up and down with K and J in visual mode"vnoremap K :m '<-2<cr>gv=gv"vnoremap J :m '>+1<cr>gv=gv"vnoremap K k"vnoremap J j" no accidental :Windows on :Wcommand! W w" no accidental ex mode (use gQ)nnoremap Q @@"nnoremap gx <cmd>exec 'new +term\ echo\ -n\ '.escape(expand('<cfile>'), '#').'\ \|\ xclip\ -sel\ clip\ &&\ w3m\ '.escape(expand('<cfile>'), '#')<cr>"nnoremap gX <cmd>exec '!open '.escape(expand('<cfile>'), '#')<cr>" remove trailing whitespace on savefunction! RemoveTrailingWhitespace()let l = line(".")let c = col(".")%s/\s\+$//ecall cursor(l, c)endfunau BufWritePre * call RemoveTrailingWhitespace()" share system clipboardset clipboard=unnamedplus" disable mouseset mouse=" aliases in :!commandslet $BASH_ENV = "~/.bash_aliases"" " autowrite mode" nnoremap <leader>a :call Autowrite()<cr>"" function! Autowrite()" if exists('#autowrite')" au! autowrite" augroup! autowrite" echo "autowrite off"" else" augroup autowrite" au!" au TextChanged,InsertLeave <buffer> silent update" echo "autowrite on"" augroup end" endif" endfunctioncolorscheme zero"set termguicolorsnnoremap <leader>c :set tgc!<cr>" reveal syntax highlight groupnnoremap <F10> :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<' . synIDattr(synID(line("."),col("."),0),"name") . "> lo<" . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<cr>" filetypesau BufRead,BufNewFile *.sls,*.sch,*sc,*.sps,*sps7 setfiletype schemeau BufRead,BufNewFile *.sw setfiletype swarm" abbreviateau FileType scheme inoreabbrev <buffer> lambda λ
syn keyword Keyword def tydef rec end let in requiresyn keyword Builtins self parent base if inl inr case fst snd force undefined fail not format chars split charat tochar keysyn keyword Command noop wait selfdestruct move backup volume path push stride turn grab harvest sow ignite place ping give equip unequip make has equipped count drill use build salvage reprogram say listen log view appear create halt time scout whereami waypoint structure floorplan hastag tagmembers detect resonate density sniff chirp watch surveil heading blocked scan upload ishere isempty meet meetall whoami setname random run return try swap atomic instant installkeyhandler teleport as robotnamed robotnumbered knowssyn keyword Direction east north west south down forward left back rightsyn match Type "\<[A-Z][a-zA-Z_]*\>"syn match Operators "[-=!<>|&+*/^$:]"syn match Comment "//.*$"syn region MultilineComment start="/\*" end="\*/"syn match Brackets "[\[\]\(\)\{\}]"syn match String "\".*\""syn match Number "\<[-]\=\d\+\>"hi def link Keyword Statementhi def link Builtins Keywordhi def link Command Functionhi def link Direction Functionhi def link Comment Commenthi def link MultilineComment Commenthi def link Brackets Keywordhi def link Operators Keywordhi def link String Stringhi def link Number Number
" Maintainer: jrvieira" To see all the current active highlight groups type" :so $VIMRUNTIME/syntax/hitest.vim"" To see all the current active highlight groups type with attributes set" :hi"" For more info" :h :hiset background=darkhi clearif exists('syntax_on')syntax resetendiflet g:colors_name='zero'" *.foreground: #d3d3d3" ! #d3d0c8" *.background: #222222" ! #2d2d2d" *.cursorColor: #79d4d5"" ! black" *.color0: #202020" *.color8: #747369"" ! red" *.color1: #f2777a" *.color9: #913535"" ! green" *.color2: #99cc99" *.color10: #a0a35d"" ! yellow" *.color3: #ffcc66" *.color11: #c47848"" ! blue" *.color4: #6699cc" *.color12: #527386"" ! magenta" *.color5: #cc99cc" *.color13: #846488"" ! cyan" *.color6: #66cccc" *.color14: #618e8b"" ! white" *.color7: #ffffff" *.color15: #969896hi ColorColumn cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi Conceal cterm=NONE ctermbg=0 ctermfg=3 gui=NONE guibg=#202020 guifg=#ffcc66hi Cursor cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#66cccc guifg=#202020hi CursorVisual cterm=NONE ctermbg=7 ctermfg=0 gui=NONE guibg=#ffffff guifg=#202020hi iCursor cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONEhi CursorLine cterm=NONE ctermbg=0 ctermfg=white gui=NONE guibg=#202020hi CursorLineNr cterm=NONE ctermbg=0 ctermfg=8 gui=NONE guibg=#202020 guifg=#747369hi TermCursor cterm=NONE ctermbg=2 ctermfg=0 gui=NONE guibg=#99cc99 guifg=#202020hi TermCursorNC cterm=NONE ctermbg=59 ctermfg=0 gui=NONE guibg=#575757 guifg=#202020hi Visual cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#66cccc guifg=#202020hi VisualNC cterm=NONE ctermbg=59 ctermfg=0 gui=NONE guibg=#575757 guifg=#202020hi VisualNOS cterm=NONE ctermbg=59 ctermfg=0 gui=NONE guibg=#575757 guifg=#202020hi Directory cterm=NONE ctermbg=NONE ctermfg=4 gui=NONE guifg=#6699cchi EndOfBuffer cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi Question cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccc"hi Question cterm=NONE ctermbg=NONE ctermfg=2 gui=NONE guifg=#99cc99hi Error cterm=NONE ctermbg=0 ctermfg=1 gui=NONE guibg=#202020 guifg=#f2777ahi ErrorMsg cterm=NONE ctermbg=0 ctermfg=1 gui=NONE guibg=#202020 guifg=#f2777ahi Folded cterm=NONE ctermbg=0 ctermfg=0 gui=NONE guibg=#202020 guifg=#202020hi FoldColumn cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi SignColumn cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi! Search cterm=inverse ctermbg=NONE ctermfg=NONE gui=inverse guibg=NONE guifg=NONEhi! link IncSearch Searchhi LineNr cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Scrollbar cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi MatchParen cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi ModeMsg cterm=NONE ctermbg=2 ctermfg=0 gui=NONE guibg=#99cc99 guifg=#202020hi NonText cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi SpellRare cterm=NONE ctermbg=NONE ctermfg=11 gui=NONE guifg=#C47848hi MsgArea cterm=NONE ctermbg=NONE ctermfg=2 gui=NONE guifg=#99cc99set fillchars=stl:hi StatusLine cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99hi StatusLineNC cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi StatusLineTerm cterm=NONE ctermbg=2 ctermfg=0 gui=NONE guibg=#99cc99 guifg=#202020hi StatusLineTermNC cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757"if exists('##TermOpen')" au TermOpen,WinEnter * if &buftype ==# 'terminal' | setl winhighlight=StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC | else | setl winhighlight= | endif"endif" status line insert mode color" if exists('##TermOpen')" augroup status_insert" au!" au insertleave * if &buftype !=# 'terminal' | hi! StatusLine cterm=NONE ctermbg=0 ctermfg=8 gui=NONE guibg=#202020 guifg=#747369 | endif" au insertenter * if &buftype !=# 'terminal' | hi! StatusLine cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccc | endif" augroup end" endif" status line insert mode color for term windowif exists('##TermOpen')au TermOpen * startinsertaugroup status_insert_termau!au termleave * if &buftype ==# 'terminal' | hi! StatusLineTerm cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99 | endifau termenter * if &buftype ==# 'terminal' | hi! StatusLineTerm cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#79d4d5 guifg=#202020 | endifaugroup endendifhi Substitute cterm=inverse ctermbg=0 ctermfg=6 gui=inverse guibg=#202020 guifg=#66cccchi TabLine cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi TabLineFill cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONEhi TabLineSel cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99"hi Title cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi VertSplit cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi WinSeparator cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi WarningMsg cterm=NONE ctermbg=NONE ctermfg=3 gui=NONE guifg=#ffcc66hi DiffText cterm=NONE ctermbg=0 ctermfg=3 gui=NONE guibg=#202020 guifg=#6699cchi DiffAdd cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99hi DiffDelete cterm=NONE ctermbg=0 ctermfg=1 gui=NONE guibg=#202020 guifg=#f2777ahi DiffChange cterm=NONE ctermbg=0 ctermfg=NONE gui=NONE guibg=#202020hi FoldColumn cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONE guibg=backgroundhi SignColumn cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONE guibg=backgroundhi! DiagnosticError cterm=NONE ctermbg=NONE ctermfg=1 gui=NONE guifg=#f2777ahi! DiagnosticWarn cterm=NONE ctermbg=NONE ctermfg=3 gui=NONE guifg=#ffcc66hi! DiagnosticInfo cterm=NONE ctermbg=NONE ctermfg=3 gui=NONE guifg=#6699cchi! DiagnosticHint cterm=NONE ctermbg=NONE ctermfg=4 gui=NONE guifg=#6699cchi! DiagnosticOk cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99hi! link DiagnosticVirtualTextError DiagnosticErrorhi! link DiagnosticVirtualTextWarn DiagnosticWarnhi! link DiagnosticVirtualTextInfo DiagnosticInfohi! link DiagnosticVirtualTextHint DiagnosticHinthi! link DiagnosticVirtualTextOk DiagnosticOkhi! link DiagnosticUnderlineError DiagnosticErrorhi! link DiagnosticUnderlineWarn DiagnosticWarnhi! link DiagnosticUnderlineInfo DiagnosticInfohi! link DiagnosticUnderlineHint DiagnosticHinthi! link DiagnosticUnderlineOk DiagnosticOkhi! link DiagnosticFloatingError DiagnosticErrorhi! link DiagnosticFloatingWarn DiagnosticWarnhi! link DiagnosticFloatingInfo DiagnosticInfohi! link DiagnosticFloatingHint DiagnosticHinthi! link DiagnosticFloatingOk DiagnosticOkhi! link DiagnosticSignError DiagnosticErrorhi! link DiagnosticSignWarn DiagnosticWarnhi! link DiagnosticSignInfo DiagnosticInfohi! link DiagnosticSignHint DiagnosticHinthi! link DiagnosticSignOk DiagnosticOkhi! MoreMsg cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi! QuickFixLine cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi! link Todo QuickFixLinehi! link WildMenu QuickFixLinehi Pmenu cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi PmenuSel cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi PmenuSbar cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi PmenuThumb cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#66cccc guifg=#202020hi! Normal cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896 guibg=NONEhi! NormalFloat guibg=#171717hi! Title cterm=NONE ctermbg=NONE ctermfg=14 gui=NONE guifg=#618E8Bhi! link LspInfoTip Titlehi! link LspInfoFiletype Titlehi! LspReferenceTarget cterm=NONE gui=NONEhi Comment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#846488hi Keyword cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Delimiter cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Include cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Type cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Function cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi Constant cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi Number cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi Character cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi String cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi Operator cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Statement cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Special cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi PreProc cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi Identifier cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi! link haskellType Typehi! link haskellKeyword Keywordhi! link haskellDelimiter Delimiterhi! link haskellComment Commenthi! link haskellSpecial Specialhi! link haskellFunction Functionhi! link haskellNumber Numberhi! link haskellCharacter Characterhi! link haskellStatement Statementhi! link haskellInclude Includehi! link haskellOperator Operator"hi! hsVarSym cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsConSym cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsLabel cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsDelimiter cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsSpecialChar cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! link hsSpecialCharError DiagnosticError"hi! hsString cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsCharacter cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsNumber cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsFloat cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsModule cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsImport cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsImportModuleName cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsImportMod cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsLineComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsBlockComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsImportList cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsImportGroup cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsTypedef cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsInfix cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsStructure cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsNewtypedef cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsTypeFam cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsStatement cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsConditional cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsPragma cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsOperator cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsLiterateComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsBoolean cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsType cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsMaybe cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsEnumConst cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsOrdering cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! link hsDebug DiagnosticWarn"hi! link hsError DiagnosticErrorhi link IlluminatedWordText MatchParenhi link IlluminatedWordRead MatchParenhi link IlluminatedWordWrite MatchParenhi FlashMatch cterm=inverse ctermbg=0 ctermfg=13 gui=inverse guibg=#202020 guifg=#846488hi FlashCurrent cterm=inverse ctermbg=0 ctermfg=13 gui=inverse guibg=#202020 guifg=#846488hi FlashLabel cterm=inverse ctermbg=0 ctermfg=5 gui=inverse guibg=#202020 guifg=#cc99cchi FlashPrompt cterm=NONE ctermbg=13 ctermfg=0 gui=NONE guibg=#846488 guifg=#202020" hilight word under cursor" " toggle" nnoremap <leader>H :call MatchBoxHL()<cr>"" function! MatchBoxHL()" if exists('#matchboxhl')" hi! MatchBoxHL NONE" au! matchboxhl" augroup! matchboxhl" setl updatetime=4000" echo 'MatchBoxHL off'" else" setl updatetime=9" " highlight the word under cursor (CursorMoved is inperformant)" hi! MatchBoxHL cterm=NONE ctermbg=NONE ctermfg=6 gui=NONE guifg=#66cccc" augroup matchboxhl" au!" " au CursorMoved * silent! exe printf('match MatchBoxHL /\V\<%s\>/', escape(expand('<cword>'), '/\'))" au CursorHold * silent! exe printf('match MatchBoxHL /\V\<%s\>/', escape(expand('<cword>'), '/\'))" au CursorMoved * silent! match none" augroup end" echo 'MatchBoxHL on'" endif" endfunction"" " on by default" silent! call MatchBoxHL()
" pluginspackloadall"syntaxsyntax on" indentationfiletype plugin indent on"set titleset tabstop=3set shiftwidth=3set expandtabset autoindentset smartindentset smarttabset shm=filmnwxosTIc" cursorset guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20set guicursor+=v:hor20-CursorVisualset laststatus=2"set statusline=%<%F\ %h%m%r%y%=%-14.(%l,%c%V%)\ %P" no modelineset noml" no show modeset nosmd" no rulerset noru" searchesset gdefaultset hlsearchset incsearchset nowrapscanset ignorecaseset smartcase " search is case sensitive iff contain uppercase charsset path+=** " recursive search with :find (provides tab completion for all file related searches)set mmp=200000 " maxmempattern" persistent undoset undofile " Save undos after file closesset undodir=$HOME/.vim/undo " where to save undo historiesset undolevels=1000 " How many undosset undoreload=10000 " number of lines to save for undo" miscset shm+=Fsset t_Co=16 " nvim lua sets this to 256set t_u7=set swapfileset writebackupset nobackupset directory=$HOME/.vim/swapfiles//set updatetime=750set showcmdset encoding=utf-8set showmatchset linebreakset scrolloff=7set nowrapset foldmethod=indentset foldnestmax=1set foldminlines=1set foldlevel=1set foldtext=set fillchars+=vert:\|"set cmdheight=0 " hide cmdline but get Hit Enter prompts" hidden charactersset listset listchars=tab:·\ ,trail:·" wildset wildmode=longest:full,fullset wildmenu" exclude newline from v$set selection=old" sign columnset scl=yes" abs + rel line numbersset nu rnu" cursor lineset cul" cul_togglefunction CulOn()augroup cul_toggleau!au InsertEnter,WinLeave,FocusLost * setl noculau InsertLeave,WinEnter,FocusGained * setl culaugroup endset culendfunctionfunction CulOff()au! cul_toggleaugroup! cul_toggleset noculendfunctionfunction CulToggle()if exists('#cul_toggle'):silent! call CulOff()else:silent! call CulOn()endifendfunctionsilent! call CulOn()command Cul call CulToggle()nnoremap <leader>C :Cul<cr>" signcolumn togglennoremap <leader>D :let currwin=win_getid() \| windo execute 'setlocal signcolumn=' . (&signcolumn ==# 'no' ? 'auto' : 'no') \| call win_gotoid(currwin) \| redraw! \| echon (&signcolumn ==# 'no' ? 'diffs off' : 'diffs on')<CR>" numbers_togglefunction NumbersOn()augroup numbers_toggleau!au insertleave,winenter,focusgained * if &buftype !=# 'terminal' | setl nu rnu | endifau insertenter,winleave,focuslost * if &buftype !=# 'terminal' | setl nu nornu | endifaugroup endwindo set nu rnuecho "numbers on"endfunctionfunction NumbersOff()au! numbers_toggleaugroup! numbers_togglewindo set nonu nornuecho "numbers off"endfunctionfunction NumbersToggle()let currwin=win_getid()if exists('#numbers_toggle'):silent! call NumbersOff()else:silent! call NumbersOn()endifcall win_gotoid(currwin)endfunctionsilent! call NumbersOff()command Numbers call NumbersToggle()nnoremap <leader>N :Numbers<cr>" if exists('##TermOpen')" au TermOpen * setl nonu nornu" au TermOpen * setl scrolloff=0" au TermEnter * match IncSearch """ endif" " hide line numbers on Terminal Insert mode" if exists('##TermOpen')" au TermOpen * setl scrolloff=0" au TermOpen * setl nu rnu" au TermEnter * match IncSearch """ au TermEnter * setl nonu nornu" au TermLeave * setl nu rnu" endif" " start :term in insert mode : causes trouble" if exists('##TermOpen')" au TermOpen * startinsert" endif" terminal normal mode window command on ^wtnoremap <C-w> <C-\><C-n><C-w>"tnoremap <esc><esc> <C-\><C-n><C-w><esc>" vertical shift variations of default commandsnnoremap <C-w>N :vnew<cr>nnoremap <C-w>S :vsplit<cr>" open a new terminal windownnoremap <C-w>t :horizontal :terminal<cr>nnoremap <C-w>T :vertical :terminal<cr>nnoremap <C-w><cr> :horizontal :terminal<cr>nnoremap <C-w><S-cr> :vertical :terminal<cr>" ^w w goes to previousnnoremap <C-w>w <C-w>pnnoremap <C-w><C-w> <C-w>p" go to previous buffernnoremap <leader><tab> :b#<cr>" infer suffixes on gf, ...set sua=.js,.hs,.rs,.py,.nim,.go" auto :noh" (remapping ESC causes weird behaviour)nnoremap <leader><space> :noh<cr>nnoremap <leader><esc> :noh<cr>nnoremap <esc> :noh<cr>" hilight current wordnnoremap <leader><leader> #*" global substitutennoremap <leader>s :%s/" global substitute current selectionvnoremap <leader>s y:%s/<C-r>"/" hilight current selectionvnoremap <cr> y/<C-r>"<cr>gv<esc>" disable auto commentau FileType * set formatoptions-=cro" neovim: incremental :sif exists('+inccommand')set inccommand=nosplitendif" default cursorslet &t_SI = "\e[6 q"let &t_SR = "\e[4 q"let &t_EI = "\e[2 q"" change cursor to pipe in insert mode"au InsertEnter * silent exe "!echo -en \<esc>[6 q""au InsertLeave * silent exe "!echo -en \<esc>[2 q"" block cursor on open" au VimEnter * silent exe "!echo -en \<esc>[2 q"" dont display the bannerlet g:netrw_banner=0" start netrw in tree view (iterate: i)let g:netrw_liststyle=3" hide dot files on start"let g:netrw_list_hide='\(^\|\s\s\)\zs\.\s\+'let g:netrw_list_hide='^\..*'let g:netrw_hide=0" auto-size netrw windowlet g:netrw_winsize= 16" close unmodified buffersau FileType netrw setl bufhidden=delete "or use :qa!" Y yanks until the end of linennoremap Y y$" go to marked columnsnnoremap ' `nnoremap ` '" " vimgrep current word" nnoremap gK :exe 'lvimgrep /\<'.expand('<cword>').'\>\C/j **/*.'.expand('%:e').' \| lw'<cr>" vnoremap gK "vy:lvimgrep /\V<C-r>v/j **/* \| lw<cr>" gp, gP pastes from "0nnoremap <leader>p "0pnnoremap <leader>P "0Pvnoremap <leader>p "0pvnoremap <leader>P "0P" put delimiters around selectionvnoremap ( c()<esc>Pgvo<esc>vnoremap ) c(<esc>pa)<esc>vnoremap g( c( <esc>pa )<esc>'[vnoremap g) c( <esc>pa )<esc>" vnoremap " <C-v>c""<esc>P% " prevents yanking to registervnoremap [ c[]<esc>Pgvo<esc>vnoremap g[ c[ <esc>pa ]<esc>'[vnoremap ] c[]<esc>P<esc>vnoremap g] c[ <esc>pa ]<esc>"vnoremap { c{}<esc>Pgvo<esc>"vnoremap g{ c{ <esc>pa }<esc>'["vnoremap } c{}<esc>P<esc>"vnoremap g} c{ <esc>pa }<esc>vnoremap < <gvvnoremap > >gv" move selection up and down with K and J in visual mode"vnoremap K :m '<-2<cr>gv=gv"vnoremap J :m '>+1<cr>gv=gv"vnoremap K k"vnoremap J j" no accidental :Windows on :Wcommand! W w" no accidental ex mode (use gQ)nnoremap Q @@"nnoremap gx <cmd>exec 'new +term\ echo\ -n\ '.escape(expand('<cfile>'), '#').'\ \|\ xclip\ -sel\ clip\ &&\ w3m\ '.escape(expand('<cfile>'), '#')<cr>"nnoremap gX <cmd>exec '!open '.escape(expand('<cfile>'), '#')<cr>" remove trailing whitespace on savefunction! RemoveTrailingWhitespace()let l = line(".")let c = col(".")%s/\s\+$//ecall cursor(l, c)endfunau BufWritePre * call RemoveTrailingWhitespace()" share system clipboardset clipboard=unnamedplus" disable mouseset mouse=" aliases in :!commandslet $BASH_ENV = "~/.bash_aliases"" " autowrite mode" nnoremap <leader>a :call Autowrite()<cr>"" function! Autowrite()" if exists('#autowrite')" au! autowrite" augroup! autowrite" echo "autowrite off"" else" augroup autowrite" au!" au TextChanged,InsertLeave <buffer> silent update" echo "autowrite on"" augroup end" endif" endfunctioncolorscheme zero"set termguicolorsnnoremap <leader>c :set tgc!<cr>" reveal syntax highlight groupnnoremap <F10> :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<' . synIDattr(synID(line("."),col("."),0),"name") . "> lo<" . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<cr>" filetypesau BufRead,BufNewFile *.sls,*.sch,*sc,*.sps,*sps7 setfiletype schemeau BufRead,BufNewFile *.sw setfiletype swarm" abbreviateau FileType scheme inoreabbrev <buffer> lambda λ
#!/bin/sh# copy cert+key from caddySRC_CRT="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/irc.jrvieira.com/irc.jrvieira.com.crt"SRC_KEY="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/irc.jrvieira.com/irc.jrvieira.com.key"DST_DIR="/etc/soju/certs"DST_CRT="${DST_DIR}/irc.jrvieira.com.crt"DST_KEY="${DST_DIR}/irc.jrvieira.com.key"# check if src existif [ ! -f "$SRC_CRT" ] || [ ! -f "$SRC_KEY" ]; thenecho "Error: source certificate files not found"exit 1fi# check if src = dstif cmp -s "$SRC_CRT" "$DST_CRT" && cmp -s "$SRC_KEY" "$DST_KEY"; thenexit 0fimkdir -p "$DST_DIR"chown _soju:_soju "$DST_DIR"chmod 750 "$DST_DIR"cp "$SRC_CRT" "$DST_CRT"chown _soju:_soju "$DST_CRT"chmod 640 "$DST_CRT"cp "$SRC_KEY" "$DST_KEY"chown _soju:_soju "$DST_KEY"chmod 600 "$DST_KEY"echo "certificates updated, reloading soju"pkill -SIGHUP -x soju
#!/bin/bash#----------------------------------------# OPTIONS#----------------------------------------USER='root' # MySQL UserPASSWORD='m1nFusion%' # MySQL PasswordDAYS_TO_KEEP=0 # 0 to keep foreverGZIP=1 # 1 = CompressBACKUP_PATH='/home/zero/backups/mysql'#----------------------------------------# Create the backup folderif [ ! -d $BACKUP_PATH ]; thenmkdir -p $BACKUP_PATHfi# Get list of database namesdatabases=`mysql -u $USER -p$PASSWORD -e "SHOW DATABASES;" | tr -d "|" | grep -v Database`for db in $databases; doif [ $db == 'information_schema' ] || [ $db == 'performance_schema' ] || [ $db == 'mysql' ] || [ $db == 'sys' ]; thenecho "Skipping database: $db"continuefidate=$(date -I)if [ "$GZIP" -eq 0 ] ; thenecho "Backing up database: $db without compression"mysqldump -u $USER -p$PASSWORD --databases $db > $BACKUP_PATH/$date-$db.sqlelseecho "Backing up database: $db with compression"mysqldump -u $USER -p$PASSWORD --databases $db | gzip -c > $BACKUP_PATH/$date-$db.gzfidone# Delete old backupsif [ "$DAYS_TO_KEEP" -gt 0 ] ; thenecho "Deleting backups older than $DAYS_TO_KEEP days"find $BACKUP_PATH/* -mtime +$DAYS_TO_KEEP -exec rm {} \;fi
#!/bin/shget_usage_span() {usage=$1if [ "$usage" -lt 5 ]; thenecho "<span color='#22222200'>⚊</span>"elif [ "$usage" -lt 25 ]; thenecho "<span color='#74736933'>⚋</span>"elif [ "$usage" -lt 45 ]; thenecho "<span color='#74736966'>⚏</span>"elif [ "$usage" -lt 65 ]; thenecho "<span color='#99cc9966'>☷</span>"elif [ "$usage" -lt 85 ]; thenecho "<span color='#99cc9999'>☳</span>"elif [ "$usage" -lt 95 ]; thenecho "<span color='#99cc99cc'>☱</span>"elseecho "<span color='#99cc99'>☰</span>"fi}# Get measurements and output barsprev_stats=$(grep "^cpu[0-9]" /proc/stat)sleep 0.5curr_stats=$(grep "^cpu[0-9]" /proc/stat)echo "$prev_stats" | while IFS= read -r prev_line; docpu_num=$(echo "$prev_line" | cut -d' ' -f1 | sed 's/cpu//')curr_line=$(echo "$curr_stats" | grep "^cpu$cpu_num ")set -- $prev_lineprev_total=$(($2 + $3 + $4 + $5))prev_idle=$5set -- $curr_linecurr_total=$(($2 + $3 + $4 + $5))curr_idle=$5total_diff=$((curr_total - prev_total))idle_diff=$((curr_idle - prev_idle))if [ $total_diff -gt 0 ]; thenusage=$(((total_diff - idle_diff) * 100 / total_diff))get_usage_span "$usage"fidone | tr -d '\n'echo
#!/bin/bash# digitalocean# sudo certbot certonly --cert-name jrvieira.com --server https://acme-v02.api.letsencrypt.org/directory --dns-digitalocean --preferred-challenges dns --dns-digitalocean-credentials /etc/letsencrypt/digitalocean/certbot-digitalocean.ini -d jrvieira.com -d *.jrvieira.com -d inwater.pt -d *.inwater.pt -d fractal-invest.pt -d *.fractal-invest.pt && sudo service nginx restart# cloudflaresudo ~/.local/bin/certbot certonly --cert-name jrvieira.com --dns-cloudflare --preferred-challenges dns --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/certbot-cloudflare.ini -d jrvieira.com -d *.jrvieira.com && sudo sv restart nginx
#!/bin/sh# copy cert+key from caddySRC_CRT="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/irc.jrvieira.com/irc.jrvieira.com.crt"SRC_KEY="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/irc.jrvieira.com/irc.jrvieira.com.key"DST_DIR="/etc/soju/certs"DST_CRT="${DST_DIR}/irc.jrvieira.com.crt"DST_KEY="${DST_DIR}/irc.jrvieira.com.key"# check if src existif [ ! -f "$SRC_CRT" ] || [ ! -f "$SRC_KEY" ]; thenecho "Error: source certificate files not found"exit 1fi# check if src = dstif cmp -s "$SRC_CRT" "$DST_CRT" && cmp -s "$SRC_KEY" "$DST_KEY"; thenexit 0fimkdir -p "$DST_DIR"chown _soju:_soju "$DST_DIR"chmod 750 "$DST_DIR"cp "$SRC_CRT" "$DST_CRT"chown _soju:_soju "$DST_CRT"chmod 640 "$DST_CRT"cp "$SRC_KEY" "$DST_KEY"chown _soju:_soju "$DST_KEY"chmod 600 "$DST_KEY"echo "certificates updated, reloading soju"pkill -SIGHUP -x soju
#!/bin/bash#----------------------------------------# OPTIONS#----------------------------------------USER='root' # MySQL UserPASSWORD='m1nFusion%' # MySQL PasswordDAYS_TO_KEEP=0 # 0 to keep foreverGZIP=1 # 1 = CompressBACKUP_PATH='/home/zero/backups/mysql'#----------------------------------------# Create the backup folderif [ ! -d $BACKUP_PATH ]; thenmkdir -p $BACKUP_PATHfi# Get list of database namesdatabases=`mysql -u $USER -p$PASSWORD -e "SHOW DATABASES;" | tr -d "|" | grep -v Database`for db in $databases; doif [ $db == 'information_schema' ] || [ $db == 'performance_schema' ] || [ $db == 'mysql' ] || [ $db == 'sys' ]; thenecho "Skipping database: $db"continuefidate=$(date -I)if [ "$GZIP" -eq 0 ] ; thenecho "Backing up database: $db without compression"mysqldump -u $USER -p$PASSWORD --databases $db > $BACKUP_PATH/$date-$db.sqlelseecho "Backing up database: $db with compression"mysqldump -u $USER -p$PASSWORD --databases $db | gzip -c > $BACKUP_PATH/$date-$db.gzfidone# Delete old backupsif [ "$DAYS_TO_KEEP" -gt 0 ] ; thenecho "Deleting backups older than $DAYS_TO_KEEP days"find $BACKUP_PATH/* -mtime +$DAYS_TO_KEEP -exec rm {} \;fi
#!/bin/shget_usage_span() {usage=$1if [ "$usage" -lt 5 ]; thenecho "<span color='#22222200'>⚊</span>"elif [ "$usage" -lt 25 ]; thenecho "<span color='#74736933'>⚋</span>"elif [ "$usage" -lt 45 ]; thenecho "<span color='#74736966'>⚏</span>"elif [ "$usage" -lt 65 ]; thenecho "<span color='#99cc9966'>☷</span>"elif [ "$usage" -lt 85 ]; thenecho "<span color='#99cc9999'>☳</span>"elif [ "$usage" -lt 95 ]; thenecho "<span color='#99cc99cc'>☱</span>"elseecho "<span color='#99cc99'>☰</span>"fi}# Get measurements and output barsprev_stats=$(grep "^cpu[0-9]" /proc/stat)sleep 0.5curr_stats=$(grep "^cpu[0-9]" /proc/stat)echo "$prev_stats" | while IFS= read -r prev_line; docpu_num=$(echo "$prev_line" | cut -d' ' -f1 | sed 's/cpu//')curr_line=$(echo "$curr_stats" | grep "^cpu$cpu_num ")set -- $prev_lineprev_total=$(($2 + $3 + $4 + $5))prev_idle=$5set -- $curr_linecurr_total=$(($2 + $3 + $4 + $5))curr_idle=$5total_diff=$((curr_total - prev_total))idle_diff=$((curr_idle - prev_idle))if [ $total_diff -gt 0 ]; thenusage=$(((total_diff - idle_diff) * 100 / total_diff))get_usage_span "$usage"fidone | tr -d '\n'echo
#!/bin/bash# digitalocean# sudo certbot certonly --cert-name jrvieira.com --server https://acme-v02.api.letsencrypt.org/directory --dns-digitalocean --preferred-challenges dns --dns-digitalocean-credentials /etc/letsencrypt/digitalocean/certbot-digitalocean.ini -d jrvieira.com -d *.jrvieira.com -d inwater.pt -d *.inwater.pt -d fractal-invest.pt -d *.fractal-invest.pt && sudo service nginx restart# cloudflaresudo ~/.local/bin/certbot certonly --cert-name jrvieira.com --dns-cloudflare --preferred-challenges dns --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/certbot-cloudflare.ini -d jrvieira.com -d *.jrvieira.com && sudo sv restart nginx
set $mod Mod4set $term kitty### Output configuration## Example configuration:## output HDMI-A-1 resolution 1920x1080 position 1920,0## You can get the names of your outputs by running: swaymsg -t get_outputsoutput * {bg ~/.jrvieira/bg.png fill #191919}### Idle configuration## Example configuration:## exec swayidle -w \# timeout 300 'swaylock -f -c 000000' \# timeout 600 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \# before-sleep 'swaylock -f -c 000000'## This will lock your screen after 300 seconds of inactivity, then turn off# your displays after another 300 seconds, and turn your screens back on when# resumed. It will also lock your screen before your computer goes to sleep.### Input configuration## Example configuration:## input "2:14:SynPS/2_Synaptics_TouchPad" {# dwt enabled# tap enabled# natural_scroll enabled# middle_emulation enabled# }## You can get the names of your inputs by running: swaymsg -t get_inputs# Read `man 5 sway-input` for more information about this section.input * {xkb_layout "us"repeat_delay 260repeat_rate 90natural_scroll enabled}# BASICS# Start a terminalbindsym $mod+return exec $term# Kill focused windowbindsym $mod+shift+q kill# Start your launcherbindsym $mod+d exec tofi-run | xargs swaymsg exec --bindsym $mod+shift+d exec tofi-drun | xargs swaymsg exec --bindsym $mod+tab exec swaymsg -t get_tree | jq -r '.. | select(type == "object" and (.type == "con" or .type == "floating_con") and .name != null) | "\(.id) \(.name)"' | tofi | awk '{print $1}' | xargs -I {} swaymsg [con_id="{}"] focus# Drag floating windows by holding down $mod and left mouse button.# Resize them with right mouse button + $mod.# Despite the name, also works for non-floating windows.# Change normal to inverse to use left mouse button for resizing and right# mouse button for dragging.floating_modifier $mod normal# Reload the configuration filebindsym $mod+shift+r reload# Exit sway (logs you out of your Wayland session)bindsym $mod+shift+e exec bash -c 'echo -e "no\nyes" | tofi --prompt-text "exit sway? " | grep -qi yes && swaymsg exit'# WORKSPACE, FOCUS AND LAYOUT# Scratchpadbindsym $mod+shift+z move scratchpadbindsym $mod+z scratchpad show# stickybindsym $mod+shift+s sticky toggle# Switch to workspacebindsym $mod+1 workspace number 1bindsym $mod+2 workspace number 2bindsym $mod+3 workspace number 3bindsym $mod+4 workspace number 4bindsym $mod+5 workspace number 5bindsym $mod+6 workspace number 6bindsym $mod+7 workspace number 7bindsym $mod+8 workspace number 8bindsym $mod+9 workspace number 9bindsym $mod+0 workspace number 10# Move focused container to workspacebindsym $mod+shift+1 move container to workspace number 1 , workspace number 1bindsym $mod+shift+2 move container to workspace number 2 , workspace number 2bindsym $mod+shift+3 move container to workspace number 3 , workspace number 3bindsym $mod+shift+4 move container to workspace number 4 , workspace number 4bindsym $mod+shift+5 move container to workspace number 5 , workspace number 5bindsym $mod+shift+6 move container to workspace number 6 , workspace number 6bindsym $mod+shift+7 move container to workspace number 7 , workspace number 7bindsym $mod+shift+8 move container to workspace number 8 , workspace number 8bindsym $mod+shift+9 move container to workspace number 9 , workspace number 9bindsym $mod+shift+0 move container to workspace number 10 , workspace number 10# Note: workspaces can have any name you want, not just numbers.# We just use 1-10 as the default.# switch to workspacebindsym $mod+n workspace next_on_outputbindsym $mod+p workspace prev_on_output# move focused container to workspacebindsym $mod+shift+n move container to workspace next_on_output , workspace next_on_outputbindsym $mod+shift+p move container to workspace prev_on_output , workspace prev_on_output# change focusbindsym $mod+h focus leftbindsym $mod+j focus downbindsym $mod+k focus upbindsym $mod+l focus rightfocus_wrapping yes# move focused windowbindsym $mod+shift+h move left 12 pxbindsym $mod+shift+j move down 12 pxbindsym $mod+shift+k move up 12 pxbindsym $mod+shift+l move right 12 px# Splitbindsym $mod+v splitvbindsym $mod+shift+v splith# Switch the current container between different layout stylesbindsym $mod+s layout stackingbindsym $mod+w layout tabbedbindsym $mod+e layout toggle split# Make the current focus fullscreenbindsym $mod+f fullscreen# Toggle the current focus between tiling and floating modebindsym $mod+shift+space floating toggle# Swap focus between the tiling area and the floating areabindsym $mod+space focus mode_toggle# Move focus to the parent containerbindsym $mod+a focus parent# focus the child containerbindsym $mod+x focus child# focus last urgentbindsym $mod+i [urgent=latest] focus# Move floating container to the centerbindsym $mod+c move position centerbindsym $mod+shift+c move position center#bindsym $mod+shift+c move absolute position center# move focus to outputbindsym $mod+o focus output nextbindsym $mod+shift+o move container to output next , focus output nextbindsym $mod+shift+w move workspace to output nextfocus_follows_mouse no# windows demanding focus will always be marked urgent but the focus will not be stolenfocus_on_window_activation urgent# RESIZEmode "resize" {bindsym h resize shrink width 10pxbindsym j resize shrink height 10pxbindsym k resize grow height 10pxbindsym l resize grow width 10px# Return to default modebindsym Return mode "default"bindsym Escape mode "default"}bindsym $mod+r mode "resize"# UTIL# Special keys to adjust volume via PulseAudiobindsym --locked XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ togglebindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -5%bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5%bindsym --locked XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle# Special keys to adjust brightness via brightnessctlbindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+# # Special key to take a screenshot with grim# bindsym Print exec grim# LOOK# no titlebarsfont pango:monospace 1for_window [title="^.*"] title_format ""titlebar_border_thickness 0titlebar_padding 0default_border pixel 0default_floating_border pixel 0# gapsbindsym $mod+g gaps inner all set 0pxbindsym $mod+shift+g gaps inner all set 12px# i3barbindsym $mod+b bar mode dockbindsym $mod+shift+b bar mode invisible# float pop-ups, don't focusno_focus [window_role="pop-up"]for_window [window_role="pop-up"] floating enablefor_window [window_role="^floating$"] floating enable# float alwaysfor_window [class="Sxiv"] floating enablefor_window [app_id="Sxiv"] floating enablefor_window [class="Nsxiv"] floating enablefor_window [app_id="Nsxiv"] floating enablefor_window [class="Vlc"] floating enablefor_window [app_id="Vlc"] floating enablefor_window [class="kitty"] floating enable , resize set 828 420for_window [app_id="kitty"] floating enable , resize set 828 420# for_window [class="Vimb"] floating enable# for_window [app_id="Vimb"] floating enable# default layout for workspace level windowsworkspace_layout tabbed# resizingset $maxw 1644set $minw 12set $maxh 1236set $minh 12# floating window sizefloating_minimum_size 12 x 12floating_maximum_size 1644 x 1236set $black #191919set $dark #222222set $tone #66ccccset $dimmed #747369set $attention #c47848# window colors# border background text indicator child_borderclient.focused $dimmed $dimmed $tone $dimmed $dimmedclient.focused_tab_title $dimmed $dimmed $blackclient.focused_inactive $dark $dark $dimmed $dark $darkclient.unfocused $black $black $dimmed $black $blackclient.urgent $attention $attention $black $attention $attention# bar# Read `man 5 sway-bar` for more information about this section.# Start i3bar to display a workspace bar (plus the system information i3status finds out, if available)bar {mode invisible# modifier Noneposition topstatus_command i3blockstray_output primary# tray_padding 0separator_symbol " "font pango:Hasklig 7colors {background $darkseparator #757575# border background textfocused_workspace $dark $dark $toneinactive_workspace $dark $dark $dimmedurgent_workspace $dark $dark $attention}}# # FX## blur enable## # blur_xray disable## # blur_passes 1# ##integer 0-10## # blur_radius 1# ##integer 0-10## # blur_noise 0.1# ##float 0-1## # blur_brightness 0.0# ##float 0-2## # blur_contrast 0.0# ##float 0-2## # blur_saturation 0# ##float 0-2## ### corner_radius 1## ### shadows enable## # shadows_on_csd disable## shadow_blur_radius 9# ##integer 0-99## shadow_color #66cccc## # shadow_offset 0 0## shadow_inactive_color #0000007F## ### # layer_effects <layer namespace> <effects># ##The current layer namespaces can be shown with swaymsg -r -t get_outputs | jq '.[0].layer_shell_surfaces | .[] | .namespace'# ##Example: layer_effects "waybar" blur enable; shadows enable; corner_radius 6# ##Effects: blur <enable|disable> | blur_ignore_transparent <enable|disable> | shadows <enable|disable> | corner_radius <int>## ### # default_dim_inactive 0# ##float 0-1## # for window [<criteria>] dim_inactive <float 0-1>## # dim_inactive_colors.unfocused #000000FF## # dim_inactive_colors.urgent #000000FF## # for_window [<criteria>] saturation <set|plus|minus> <vale 0.0 <-> 2.0>## titlebar_separator disable## # scratchpad_minimize <enable|disable># ##recommend off (buggy)# MISC# shot# monitorbindsym $mod+t exec grim# regionbindsym $mod+shift+t exec grim -g "$(slurp -w 0)"# set audioexec pipewire#exec gammastep -l 41.1:-8.6exec wlsunset -l 41.1 -L -8.6exec mako# machine specificexec ~/this# # launch terminal# exec $terminclude /etc/sway/config.d/*
set $mod Mod4set $term kitty### Output configuration## Example configuration:## output HDMI-A-1 resolution 1920x1080 position 1920,0## You can get the names of your outputs by running: swaymsg -t get_outputsoutput * {bg ~/.jrvieira/bg.png fill #191919}### Idle configuration## Example configuration:## exec swayidle -w \# timeout 300 'swaylock -f -c 000000' \# timeout 600 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \# before-sleep 'swaylock -f -c 000000'## This will lock your screen after 300 seconds of inactivity, then turn off# your displays after another 300 seconds, and turn your screens back on when# resumed. It will also lock your screen before your computer goes to sleep.### Input configuration## Example configuration:## input "2:14:SynPS/2_Synaptics_TouchPad" {# dwt enabled# tap enabled# natural_scroll enabled# middle_emulation enabled# }## You can get the names of your inputs by running: swaymsg -t get_inputs# Read `man 5 sway-input` for more information about this section.input * {xkb_layout "us"repeat_delay 260repeat_rate 90natural_scroll enabled}# BASICS# Start a terminalbindsym $mod+return exec $term# Kill focused windowbindsym $mod+shift+q kill# Start your launcherbindsym $mod+d exec tofi-run | xargs swaymsg exec --bindsym $mod+shift+d exec tofi-drun | xargs swaymsg exec --bindsym $mod+tab exec swaymsg -t get_tree | jq -r '.. | select(type == "object" and (.type == "con" or .type == "floating_con") and .name != null) | "\(.id) \(.name)"' | tofi | awk '{print $1}' | xargs -I {} swaymsg [con_id="{}"] focus# Drag floating windows by holding down $mod and left mouse button.# Resize them with right mouse button + $mod.# Despite the name, also works for non-floating windows.# Change normal to inverse to use left mouse button for resizing and right# mouse button for dragging.floating_modifier $mod normal# Reload the configuration filebindsym $mod+shift+r reload# Exit sway (logs you out of your Wayland session)bindsym $mod+shift+e exec bash -c 'echo -e "no\nyes" | tofi --prompt-text "exit sway? " | grep -qi yes && swaymsg exit'# WORKSPACE, FOCUS AND LAYOUT# Scratchpadbindsym $mod+shift+z move scratchpadbindsym $mod+z scratchpad show# stickybindsym $mod+shift+s sticky toggle# Switch to workspacebindsym $mod+1 workspace number 1bindsym $mod+2 workspace number 2bindsym $mod+3 workspace number 3bindsym $mod+4 workspace number 4bindsym $mod+5 workspace number 5bindsym $mod+6 workspace number 6bindsym $mod+7 workspace number 7bindsym $mod+8 workspace number 8bindsym $mod+9 workspace number 9bindsym $mod+0 workspace number 10# Move focused container to workspacebindsym $mod+shift+1 move container to workspace number 1 , workspace number 1bindsym $mod+shift+2 move container to workspace number 2 , workspace number 2bindsym $mod+shift+3 move container to workspace number 3 , workspace number 3bindsym $mod+shift+4 move container to workspace number 4 , workspace number 4bindsym $mod+shift+5 move container to workspace number 5 , workspace number 5bindsym $mod+shift+6 move container to workspace number 6 , workspace number 6bindsym $mod+shift+7 move container to workspace number 7 , workspace number 7bindsym $mod+shift+8 move container to workspace number 8 , workspace number 8bindsym $mod+shift+9 move container to workspace number 9 , workspace number 9bindsym $mod+shift+0 move container to workspace number 10 , workspace number 10# Note: workspaces can have any name you want, not just numbers.# We just use 1-10 as the default.# switch to workspacebindsym $mod+n workspace next_on_outputbindsym $mod+p workspace prev_on_output# move focused container to workspacebindsym $mod+shift+n move container to workspace next_on_output , workspace next_on_outputbindsym $mod+shift+p move container to workspace prev_on_output , workspace prev_on_output# change focusbindsym $mod+h focus leftbindsym $mod+j focus downbindsym $mod+k focus upbindsym $mod+l focus rightfocus_wrapping yes# move focused windowbindsym $mod+shift+h move left 12 pxbindsym $mod+shift+j move down 12 pxbindsym $mod+shift+k move up 12 pxbindsym $mod+shift+l move right 12 px# Splitbindsym $mod+v splitvbindsym $mod+shift+v splith# Switch the current container between different layout stylesbindsym $mod+s layout stackingbindsym $mod+w layout tabbedbindsym $mod+e layout toggle split# Make the current focus fullscreenbindsym $mod+f fullscreen# Toggle the current focus between tiling and floating modebindsym $mod+shift+space floating toggle# Swap focus between the tiling area and the floating areabindsym $mod+space focus mode_toggle# Move focus to the parent containerbindsym $mod+a focus parent# focus the child containerbindsym $mod+x focus child# focus last urgentbindsym $mod+i [urgent=latest] focus# Move floating container to the centerbindsym $mod+c move position centerbindsym $mod+shift+c move position center#bindsym $mod+shift+c move absolute position center# move focus to outputbindsym $mod+o focus output nextbindsym $mod+shift+o move container to output next , focus output nextbindsym $mod+shift+w move workspace to output nextfocus_follows_mouse no# windows demanding focus will always be marked urgent but the focus will not be stolenfocus_on_window_activation urgent# RESIZEmode "resize" {bindsym h resize shrink width 10pxbindsym j resize shrink height 10pxbindsym k resize grow height 10pxbindsym l resize grow width 10px# Return to default modebindsym Return mode "default"bindsym Escape mode "default"}bindsym $mod+r mode "resize"# UTIL# Special keys to adjust volume via PulseAudiobindsym --locked XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ togglebindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -5%bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5%bindsym --locked XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle# Special keys to adjust brightness via brightnessctlbindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+# # Special key to take a screenshot with grim# bindsym Print exec grim# LOOK# no titlebarsfont pango:monospace 1for_window [title="^.*"] title_format ""titlebar_border_thickness 0titlebar_padding 0default_border pixel 0default_floating_border pixel 0# gapsbindsym $mod+g gaps inner all set 0pxbindsym $mod+shift+g gaps inner all set 12px# i3barbindsym $mod+b bar mode dockbindsym $mod+shift+b bar mode invisible# float pop-ups, don't focusno_focus [window_role="pop-up"]for_window [window_role="pop-up"] floating enablefor_window [window_role="^floating$"] floating enable# float alwaysfor_window [class="Sxiv"] floating enablefor_window [app_id="Sxiv"] floating enablefor_window [class="Nsxiv"] floating enablefor_window [app_id="Nsxiv"] floating enablefor_window [class="Vlc"] floating enablefor_window [app_id="Vlc"] floating enablefor_window [class="kitty"] floating enable , resize set 828 420for_window [app_id="kitty"] floating enable , resize set 828 420# for_window [class="Vimb"] floating enable# for_window [app_id="Vimb"] floating enable# default layout for workspace level windowsworkspace_layout tabbed# resizingset $maxw 1644set $minw 12set $maxh 1236set $minh 12# floating window sizefloating_minimum_size 12 x 12floating_maximum_size 1644 x 1236set $black #191919set $dark #222222set $tone #66ccccset $dimmed #747369set $attention #c47848# window colors# border background text indicator child_borderclient.focused $dimmed $dimmed $tone $dimmed $dimmedclient.focused_tab_title $dimmed $dimmed $blackclient.focused_inactive $dark $dark $dimmed $dark $darkclient.unfocused $black $black $dimmed $black $blackclient.urgent $attention $attention $black $attention $attention# bar# Read `man 5 sway-bar` for more information about this section.# Start i3bar to display a workspace bar (plus the system information i3status finds out, if available)bar {mode invisible# modifier Noneposition topstatus_command i3blockstray_output primary# tray_padding 0separator_symbol " "font pango:Hasklig 7colors {background $darkseparator #757575# border background textfocused_workspace $dark $dark $toneinactive_workspace $dark $dark $dimmedurgent_workspace $dark $dark $attention}}# # FX## blur enable## # blur_xray disable## # blur_passes 1# ##integer 0-10## # blur_radius 1# ##integer 0-10## # blur_noise 0.1# ##float 0-1## # blur_brightness 0.0# ##float 0-2## # blur_contrast 0.0# ##float 0-2## # blur_saturation 0# ##float 0-2## ### corner_radius 1## ### shadows enable## # shadows_on_csd disable## shadow_blur_radius 9# ##integer 0-99## shadow_color #66cccc## # shadow_offset 0 0## shadow_inactive_color #0000007F## ### # layer_effects <layer namespace> <effects># ##The current layer namespaces can be shown with swaymsg -r -t get_outputs | jq '.[0].layer_shell_surfaces | .[] | .namespace'# ##Example: layer_effects "waybar" blur enable; shadows enable; corner_radius 6# ##Effects: blur <enable|disable> | blur_ignore_transparent <enable|disable> | shadows <enable|disable> | corner_radius <int>## ### # default_dim_inactive 0# ##float 0-1## # for window [<criteria>] dim_inactive <float 0-1>## # dim_inactive_colors.unfocused #000000FF## # dim_inactive_colors.urgent #000000FF## # for_window [<criteria>] saturation <set|plus|minus> <vale 0.0 <-> 2.0>## titlebar_separator disable## # scratchpad_minimize <enable|disable># ##recommend off (buggy)# MISC# shot# monitorbindsym $mod+t exec grim# regionbindsym $mod+shift+t exec grim -g "$(slurp -w 0)"# set audioexec pipewire#exec gammastep -l 41.1:-8.6exec wlsunset -l 41.1 -L -8.6exec mako# machine specificexec ~/this# # launch terminal# exec $terminclude /etc/sway/config.d/*
#!/bin/sh[ -r ./conf ] && . ./conf[ -n "$core_services" ] && SVDIR=".." sv start $core_servicesif [ -n "$core_services" ]; thenuntil SVDIR=".." sv check $core_services; do:donefi[ -p "/run/turnstiled/1000/ready" ] && printf "/home/zero/.config/service/turnstile-ready" > "/run/turnstiled/1000/ready"exec pause
#!/bin/sh[ -r ./conf ] && . ./conf[ -n "$core_services" ] && SVDIR=".." sv start $core_servicesif [ -n "$core_services" ]; thenuntil SVDIR=".." sv check $core_services; do:donefi[ -p "/run/turnstiled/1000/ready" ] && printf "/home/zero/.config/service/turnstile-ready" > "/run/turnstiled/1000/ready"exec pause
#!/bin/shexec chpst -e "$TURNSTILE_ENV_DIR" pipewire
#!/bin/sh[ -r ./conf ] && . ./conf: "${DBUS_SESSION_BUS_ADDRESS:=unix:path=/run/user/$(id -u)/bus}"if [ -d "$TURNSTILE_ENV_DIR" ]; thenecho "$DBUS_SESSION_BUS_ADDRESS" > "$TURNSTILE_ENV_DIR"/DBUS_SESSION_BUS_ADDRESSfiexec chpst -e "$TURNSTILE_ENV_DIR" dbus-daemon --session --nofork --nopidfile --address="$DBUS_SESSION_BUS_ADDRESS" $OPTS
#!/bin/shexec dbus-send --bus="unix:path=$XDG_RUNTIME_DIR/bus" / org.freedesktop.DBus.Peer.Ping > /dev/null 2> /dev/null
#!/bin/sh[ -r ./conf ] && . ./conf: "${DBUS_SESSION_BUS_ADDRESS:=unix:path=/run/user/$(id -u)/bus}"if [ -d "$TURNSTILE_ENV_DIR" ]; thenecho "$DBUS_SESSION_BUS_ADDRESS" > "$TURNSTILE_ENV_DIR"/DBUS_SESSION_BUS_ADDRESSfiexec chpst -e "$TURNSTILE_ENV_DIR" dbus-daemon --session --nofork --nopidfile --address="$DBUS_SESSION_BUS_ADDRESS" $OPTS
#!/bin/shexec dbus-send --bus="unix:path=$XDG_RUNTIME_DIR/bus" / org.freedesktop.DBus.Peer.Ping > /dev/null 2> /dev/null
/* zero-dark theme */* {font: "Hasklig 7";background-color: #222222;text-color: #676E7D;}window {padding: 60px;fullscreen: true;}inputbar {padding: 0px 0px 10px 0px;}prompt {text-color: #79d4d5;padding: 0px 6px 0px 0px;}entry {text-color: #d3d3d3;}element normal {text-color: #747369;}element selected {text-color: #79d4d5;}element-text {highlight: none;background-color: inherit;text-color: inherit;}
configuration {/* modi: "window,run,ssh";*//* width: 50;*//* lines: 15;*//* columns: 1;*//* font: "mono 12";*//* bw: 1;*//* location: 0;*//* padding: 5;*//* yoffset: 0;*//* xoffset: 0;*//* fixed-num-lines: true;*//* show-icons: false;*//* terminal: "rofi-sensible-terminal";*//* ssh-client: "ssh";*//* ssh-command: "{terminal} -e {ssh-client} {host}";*//* run-command: "{cmd}";*//* run-list-command: "";*//* run-shell-command: "{terminal} -e {cmd}";*//* window-command: "xkill -id {window}";*//* window-match-fields: "all";*//* drun-icon-útheme: ;*//* drun-match-fields: "name,generic,exec,categories";*//* disable-history: false;*//* sort: false;*//* levenshtein-sort: false;*//* case-sensitive: false;*//* cycle: true;*//* sidebar-mode: false;*//* eh: 1;*//* auto-select: false;*//* parse-hosts: false;*//* parse-known-hosts: true;*//* combi-modi: "window,run";*//* matching: "normal";*//* tokenize: true;*//* m: "-5";*//* line-margin: 2;*//* line-padding: 1;*//* filter: ;*//* separator-style: "dash";*//* hide-scrollbar: false;*//* fullscreen: false;*//* fake-transparency: false;*//* dpi: -1;*//* threads: 0;*//* scrollbar-width: 8;*//* scroll-method: 0;*//* fake-background: "screenshot";*//* window-format: "{w} {i}{c} {t}";*//* click-to-exit: true;*//* show-match: true;*/theme: "zero-dark";/* color-normal: ;*//* color-urgent: ;*//* color-active: ;*//* color-window: ;*//* max-history-size: 25;*//* combi-hide-mode-prefix: false;*//* pid: "/run/user/1000/rofi.pid";*//* display-window: ;*//* display-windowcd: ;*//* display-run: ;*//* display-ssh: ;*//* display-drun: ;*//* display-combi: ;*//* display-keys: ;*//* kb-primary-paste: "Control+V,Shift+Insert";*//* kb-secondary-paste: "Control+v,Insert";*//* kb-clear-line: "Control+w";*//* kb-move-front: "Control+a";*//* kb-move-end: "Control+e";*//* kb-move-word-back: "Alt+b";*//* kb-move-word-forward: "Alt+f";*//* kb-move-char-back: "Left,Control+b";*//* kb-move-char-forward: "Right,Control+f";*//* kb-remove-word-back: "Control+Alt+h,Control+BackSpace";*//* kb-remove-word-forward: "Control+Alt+d";*//* kb-remove-char-forward: "Delete,Control+d";*//* kb-remove-char-back: "BackSpace,Control+h";*//* kb-remove-to-eol: "Control+k";*//* kb-remove-to-sol: "Control+u";*//* kb-accept-entry: "Control+j,Control+m,Return,KP_Enter";*//* kb-accept-custom: "Control+Return";*//* kb-accept-alt: "Shift+Return";*//* kb-delete-entry: "Shift+Delete";*//* kb-mode-next: "Shift+Right,Control+Tab";*//* kb-mode-previous: "Shift+Left,Control+ISO_Left_Tab";*//* kb-row-left: "Control+Page_Up";*//* kb-row-right: "Control+Page_Down";*//* kb-row-up: "Up,Control+p,ISO_Left_Tab";*//* kb-row-down: "Down,Control+n";*//* kb-row-tab: "Tab";*//* kb-page-prev: "Page_Up";*//* kb-page-next: "Page_Down";*//* kb-row-first: "Home,KP_Home";*//* kb-row-last: "End,KP_End";*//* kb-row-select: "Control+space";*//* kb-screenshot: "Alt+S";*//* kb-toggle-case-sensitivity: "grave,dead_grave";*//* kb-toggle-sort: "Alt+grave";*//* kb-cancel: "Escape,Control+g,Control+bracketleft";*//* kb-custom-1: "Alt+1";*//* kb-custom-2: "Alt+2";*//* kb-custom-3: "Alt+3";*//* kb-custom-4: "Alt+4";*//* kb-custom-5: "Alt+5";*//* kb-custom-6: "Alt+6";*//* kb-custom-7: "Alt+7";*//* kb-custom-8: "Alt+8";*//* kb-custom-9: "Alt+9";*//* kb-custom-10: "Alt+0";*//* kb-custom-11: "Alt+exclam";*//* kb-custom-12: "Alt+at";*//* kb-custom-13: "Alt+numbersign";*//* kb-custom-14: "Alt+dollar";*//* kb-custom-15: "Alt+percent";*//* kb-custom-16: "Alt+dead_circumflex";*//* kb-custom-17: "Alt+ampersand";*//* kb-custom-18: "Alt+asterisk";*//* kb-custom-19: "Alt+parenleft";*//* kb-select-1: "Super+1";*//* kb-select-2: "Super+2";*//* kb-select-3: "Super+3";*//* kb-select-4: "Super+4";*//* kb-select-5: "Super+5";*//* kb-select-6: "Super+6";*//* kb-select-7: "Super+7";*//* kb-select-8: "Super+8";*//* kb-select-9: "Super+9";*//* kb-select-10: "Super+0";*//* ml-row-left: "ScrollLeft";*//* ml-row-right: "ScrollRight";*//* ml-row-up: "ScrollUp";*//* ml-row-down: "ScrollDown";*//* me-select-entry: "MousePrimary";*//* me-accept-entry: "MouseDPrimary";*//* me-accept-custom: "Control+MouseDPrimary";*/}@import "/usr/share/rofi/themes/c64.rasi"
configuration {modi: "window,run,ssh,drun";font: "Hasklig 7";fixed-num-lines: true;disable-history: false;case-sensitive: false;cycle: true;eh: 2;matching: "normal";}@theme "zero-dark.rasi"
/* zero-dark theme */* {font: "Hasklig 7";background-color: #222222;text-color: #676E7D;}window {padding: 60px;fullscreen: true;}inputbar {padding: 0px 0px 10px 0px;}prompt {text-color: #79d4d5;padding: 0px 6px 0px 0px;}entry {text-color: #d3d3d3;}element normal {text-color: #747369;}element selected {text-color: #79d4d5;}element-text {highlight: none;background-color: inherit;text-color: inherit;}
configuration {/* modi: "window,run,ssh";*//* width: 50;*//* lines: 15;*//* columns: 1;*//* font: "mono 12";*//* bw: 1;*//* location: 0;*//* padding: 5;*//* yoffset: 0;*//* xoffset: 0;*//* fixed-num-lines: true;*//* show-icons: false;*//* terminal: "rofi-sensible-terminal";*//* ssh-client: "ssh";*//* ssh-command: "{terminal} -e {ssh-client} {host}";*//* run-command: "{cmd}";*//* run-list-command: "";*//* run-shell-command: "{terminal} -e {cmd}";*//* window-command: "xkill -id {window}";*//* window-match-fields: "all";*//* drun-icon-útheme: ;*//* drun-match-fields: "name,generic,exec,categories";*//* disable-history: false;*//* sort: false;*//* levenshtein-sort: false;*//* case-sensitive: false;*//* cycle: true;*//* sidebar-mode: false;*//* eh: 1;*//* auto-select: false;*//* parse-hosts: false;*//* parse-known-hosts: true;*//* combi-modi: "window,run";*//* matching: "normal";*//* tokenize: true;*//* m: "-5";*//* line-margin: 2;*//* line-padding: 1;*//* filter: ;*//* separator-style: "dash";*//* hide-scrollbar: false;*//* fullscreen: false;*//* fake-transparency: false;*//* dpi: -1;*//* threads: 0;*//* scrollbar-width: 8;*//* scroll-method: 0;*//* fake-background: "screenshot";*//* window-format: "{w} {i}{c} {t}";*//* click-to-exit: true;*//* show-match: true;*/theme: "zero-dark";/* color-normal: ;*//* color-urgent: ;*//* color-active: ;*//* color-window: ;*//* max-history-size: 25;*//* combi-hide-mode-prefix: false;*//* pid: "/run/user/1000/rofi.pid";*//* display-window: ;*//* display-windowcd: ;*//* display-run: ;*//* display-ssh: ;*//* display-drun: ;*//* display-combi: ;*//* display-keys: ;*//* kb-primary-paste: "Control+V,Shift+Insert";*//* kb-secondary-paste: "Control+v,Insert";*//* kb-clear-line: "Control+w";*//* kb-move-front: "Control+a";*//* kb-move-end: "Control+e";*//* kb-move-word-back: "Alt+b";*//* kb-move-word-forward: "Alt+f";*//* kb-move-char-back: "Left,Control+b";*//* kb-move-char-forward: "Right,Control+f";*//* kb-remove-word-back: "Control+Alt+h,Control+BackSpace";*//* kb-remove-word-forward: "Control+Alt+d";*//* kb-remove-char-forward: "Delete,Control+d";*//* kb-remove-char-back: "BackSpace,Control+h";*//* kb-remove-to-eol: "Control+k";*//* kb-remove-to-sol: "Control+u";*//* kb-accept-entry: "Control+j,Control+m,Return,KP_Enter";*//* kb-accept-custom: "Control+Return";*//* kb-accept-alt: "Shift+Return";*//* kb-delete-entry: "Shift+Delete";*//* kb-mode-next: "Shift+Right,Control+Tab";*//* kb-mode-previous: "Shift+Left,Control+ISO_Left_Tab";*//* kb-row-left: "Control+Page_Up";*//* kb-row-right: "Control+Page_Down";*//* kb-row-up: "Up,Control+p,ISO_Left_Tab";*//* kb-row-down: "Down,Control+n";*//* kb-row-tab: "Tab";*//* kb-page-prev: "Page_Up";*//* kb-page-next: "Page_Down";*//* kb-row-first: "Home,KP_Home";*//* kb-row-last: "End,KP_End";*//* kb-row-select: "Control+space";*//* kb-screenshot: "Alt+S";*//* kb-toggle-case-sensitivity: "grave,dead_grave";*//* kb-toggle-sort: "Alt+grave";*//* kb-cancel: "Escape,Control+g,Control+bracketleft";*//* kb-custom-1: "Alt+1";*//* kb-custom-2: "Alt+2";*//* kb-custom-3: "Alt+3";*//* kb-custom-4: "Alt+4";*//* kb-custom-5: "Alt+5";*//* kb-custom-6: "Alt+6";*//* kb-custom-7: "Alt+7";*//* kb-custom-8: "Alt+8";*//* kb-custom-9: "Alt+9";*//* kb-custom-10: "Alt+0";*//* kb-custom-11: "Alt+exclam";*//* kb-custom-12: "Alt+at";*//* kb-custom-13: "Alt+numbersign";*//* kb-custom-14: "Alt+dollar";*//* kb-custom-15: "Alt+percent";*//* kb-custom-16: "Alt+dead_circumflex";*//* kb-custom-17: "Alt+ampersand";*//* kb-custom-18: "Alt+asterisk";*//* kb-custom-19: "Alt+parenleft";*//* kb-select-1: "Super+1";*//* kb-select-2: "Super+2";*//* kb-select-3: "Super+3";*//* kb-select-4: "Super+4";*//* kb-select-5: "Super+5";*//* kb-select-6: "Super+6";*//* kb-select-7: "Super+7";*//* kb-select-8: "Super+8";*//* kb-select-9: "Super+9";*//* kb-select-10: "Super+0";*//* ml-row-left: "ScrollLeft";*//* ml-row-right: "ScrollRight";*//* ml-row-up: "ScrollUp";*//* ml-row-down: "ScrollDown";*//* me-select-entry: "MousePrimary";*//* me-accept-entry: "MouseDPrimary";*//* me-accept-custom: "Control+MouseDPrimary";*/}@import "/usr/share/rofi/themes/c64.rasi"
configuration {modi: "window,run,ssh,drun";font: "Hasklig 7";fixed-num-lines: true;disable-history: false;case-sensitive: false;cycle: true;eh: 2;matching: "normal";}@theme "zero-dark.rasi"
syn keyword Keyword def tydef rec end let in requiresyn keyword Builtins self parent base if inl inr case fst snd force undefined fail not format chars split charat tochar keysyn keyword Command noop wait selfdestruct move backup volume path push stride turn grab harvest sow ignite place ping give equip unequip make has equipped count drill use build salvage reprogram say listen log view appear create halt time scout whereami waypoint structure floorplan hastag tagmembers detect resonate density sniff chirp watch surveil heading blocked scan upload ishere isempty meet meetall whoami setname random run return try swap atomic instant installkeyhandler teleport as robotnamed robotnumbered knowssyn keyword Direction east north west south down forward left back rightsyn match Type "\<[A-Z][a-zA-Z_]*\>"syn match Operators "[-=!<>|&+*/^$:]"syn match Comment "//.*$"syn region MultilineComment start="/\*" end="\*/"syn match Brackets "[\[\]\(\)\{\}]"syn match String "\".*\""syn match Number "\<[-]\=\d\+\>"hi def link Keyword Statementhi def link Builtins Keywordhi def link Command Functionhi def link Direction Functionhi def link Comment Commenthi def link MultilineComment Commenthi def link Brackets Keywordhi def link Operators Keywordhi def link String Stringhi def link Number Number
" Maintainer: jrvieira" To see all the current active highlight groups type" :so $VIMRUNTIME/syntax/hitest.vim"" To see all the current active highlight groups type with attributes set" :hi"" For more info" :h :hiset background=darkhi clearif exists('syntax_on')syntax resetendiflet g:colors_name='zero'" *.foreground: #d3d3d3" ! #d3d0c8" *.background: #222222" ! #2d2d2d" *.cursorColor: #79d4d5"" ! black" *.color0: #202020" *.color8: #747369"" ! red" *.color1: #f2777a" *.color9: #913535"" ! green" *.color2: #99cc99" *.color10: #a0a35d"" ! yellow" *.color3: #ffcc66" *.color11: #c47848"" ! blue" *.color4: #6699cc" *.color12: #527386"" ! magenta" *.color5: #cc99cc" *.color13: #846488"" ! cyan" *.color6: #66cccc" *.color14: #618e8b"" ! white" *.color7: #ffffff" *.color15: #969896hi ColorColumn cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi Conceal cterm=NONE ctermbg=0 ctermfg=3 gui=NONE guibg=#202020 guifg=#ffcc66hi Cursor cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#66cccc guifg=#202020hi CursorVisual cterm=NONE ctermbg=7 ctermfg=0 gui=NONE guibg=#ffffff guifg=#202020hi iCursor cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONEhi CursorLine cterm=NONE ctermbg=0 ctermfg=white gui=NONE guibg=#202020hi CursorLineNr cterm=NONE ctermbg=0 ctermfg=8 gui=NONE guibg=#202020 guifg=#747369hi TermCursor cterm=NONE ctermbg=2 ctermfg=0 gui=NONE guibg=#99cc99 guifg=#202020hi TermCursorNC cterm=NONE ctermbg=59 ctermfg=0 gui=NONE guibg=#575757 guifg=#202020hi Visual cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#66cccc guifg=#202020hi VisualNC cterm=NONE ctermbg=59 ctermfg=0 gui=NONE guibg=#575757 guifg=#202020hi VisualNOS cterm=NONE ctermbg=59 ctermfg=0 gui=NONE guibg=#575757 guifg=#202020hi Directory cterm=NONE ctermbg=NONE ctermfg=4 gui=NONE guifg=#6699cchi EndOfBuffer cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi Question cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccc"hi Question cterm=NONE ctermbg=NONE ctermfg=2 gui=NONE guifg=#99cc99hi Error cterm=NONE ctermbg=0 ctermfg=1 gui=NONE guibg=#202020 guifg=#f2777ahi ErrorMsg cterm=NONE ctermbg=0 ctermfg=1 gui=NONE guibg=#202020 guifg=#f2777ahi Folded cterm=NONE ctermbg=0 ctermfg=0 gui=NONE guibg=#202020 guifg=#202020hi FoldColumn cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi SignColumn cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi! Search cterm=inverse ctermbg=NONE ctermfg=NONE gui=inverse guibg=NONE guifg=NONEhi! link IncSearch Searchhi LineNr cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Scrollbar cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi MatchParen cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi ModeMsg cterm=NONE ctermbg=2 ctermfg=0 gui=NONE guibg=#99cc99 guifg=#202020hi NonText cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi SpellRare cterm=NONE ctermbg=NONE ctermfg=11 gui=NONE guifg=#C47848hi MsgArea cterm=NONE ctermbg=NONE ctermfg=2 gui=NONE guifg=#99cc99set fillchars=stl:hi StatusLine cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99hi StatusLineNC cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi StatusLineTerm cterm=NONE ctermbg=2 ctermfg=0 gui=NONE guibg=#99cc99 guifg=#202020hi StatusLineTermNC cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757"if exists('##TermOpen')" au TermOpen,WinEnter * if &buftype ==# 'terminal' | setl winhighlight=StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC | else | setl winhighlight= | endif"endif" status line insert mode color" if exists('##TermOpen')" augroup status_insert" au!" au insertleave * if &buftype !=# 'terminal' | hi! StatusLine cterm=NONE ctermbg=0 ctermfg=8 gui=NONE guibg=#202020 guifg=#747369 | endif" au insertenter * if &buftype !=# 'terminal' | hi! StatusLine cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccc | endif" augroup end" endif" status line insert mode color for term windowif exists('##TermOpen')au TermOpen * startinsertaugroup status_insert_termau!au termleave * if &buftype ==# 'terminal' | hi! StatusLineTerm cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99 | endifau termenter * if &buftype ==# 'terminal' | hi! StatusLineTerm cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#79d4d5 guifg=#202020 | endifaugroup endendifhi Substitute cterm=inverse ctermbg=0 ctermfg=6 gui=inverse guibg=#202020 guifg=#66cccchi TabLine cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi TabLineFill cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONEhi TabLineSel cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99"hi Title cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi VertSplit cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi WinSeparator cterm=NONE ctermbg=NONE ctermfg=0 gui=NONE guifg=#202020hi WarningMsg cterm=NONE ctermbg=NONE ctermfg=3 gui=NONE guifg=#ffcc66hi DiffText cterm=NONE ctermbg=0 ctermfg=3 gui=NONE guibg=#202020 guifg=#6699cchi DiffAdd cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99hi DiffDelete cterm=NONE ctermbg=0 ctermfg=1 gui=NONE guibg=#202020 guifg=#f2777ahi DiffChange cterm=NONE ctermbg=0 ctermfg=NONE gui=NONE guibg=#202020hi FoldColumn cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONE guibg=backgroundhi SignColumn cterm=NONE ctermbg=NONE ctermfg=NONE gui=NONE guibg=backgroundhi! DiagnosticError cterm=NONE ctermbg=NONE ctermfg=1 gui=NONE guifg=#f2777ahi! DiagnosticWarn cterm=NONE ctermbg=NONE ctermfg=3 gui=NONE guifg=#ffcc66hi! DiagnosticInfo cterm=NONE ctermbg=NONE ctermfg=3 gui=NONE guifg=#6699cchi! DiagnosticHint cterm=NONE ctermbg=NONE ctermfg=4 gui=NONE guifg=#6699cchi! DiagnosticOk cterm=NONE ctermbg=0 ctermfg=2 gui=NONE guibg=#202020 guifg=#99cc99hi! link DiagnosticVirtualTextError DiagnosticErrorhi! link DiagnosticVirtualTextWarn DiagnosticWarnhi! link DiagnosticVirtualTextInfo DiagnosticInfohi! link DiagnosticVirtualTextHint DiagnosticHinthi! link DiagnosticVirtualTextOk DiagnosticOkhi! link DiagnosticUnderlineError DiagnosticErrorhi! link DiagnosticUnderlineWarn DiagnosticWarnhi! link DiagnosticUnderlineInfo DiagnosticInfohi! link DiagnosticUnderlineHint DiagnosticHinthi! link DiagnosticUnderlineOk DiagnosticOkhi! link DiagnosticFloatingError DiagnosticErrorhi! link DiagnosticFloatingWarn DiagnosticWarnhi! link DiagnosticFloatingInfo DiagnosticInfohi! link DiagnosticFloatingHint DiagnosticHinthi! link DiagnosticFloatingOk DiagnosticOkhi! link DiagnosticSignError DiagnosticErrorhi! link DiagnosticSignWarn DiagnosticWarnhi! link DiagnosticSignInfo DiagnosticInfohi! link DiagnosticSignHint DiagnosticHinthi! link DiagnosticSignOk DiagnosticOkhi! MoreMsg cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi! QuickFixLine cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi! link Todo QuickFixLinehi! link WildMenu QuickFixLinehi Pmenu cterm=NONE ctermbg=0 ctermfg=59 gui=NONE guibg=#202020 guifg=#575757hi PmenuSel cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi PmenuSbar cterm=NONE ctermbg=0 ctermfg=6 gui=NONE guibg=#202020 guifg=#66cccchi PmenuThumb cterm=NONE ctermbg=6 ctermfg=0 gui=NONE guibg=#66cccc guifg=#202020hi! Normal cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896 guibg=NONEhi! NormalFloat guibg=#171717hi! Title cterm=NONE ctermbg=NONE ctermfg=14 gui=NONE guifg=#618E8Bhi! link LspInfoTip Titlehi! link LspInfoFiletype Titlehi! LspReferenceTarget cterm=NONE gui=NONEhi Comment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#846488hi Keyword cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Delimiter cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Include cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Type cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Function cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi Constant cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi Number cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi Character cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi String cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369hi Operator cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Statement cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757hi Special cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi PreProc cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi Identifier cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896hi! link haskellType Typehi! link haskellKeyword Keywordhi! link haskellDelimiter Delimiterhi! link haskellComment Commenthi! link haskellSpecial Specialhi! link haskellFunction Functionhi! link haskellNumber Numberhi! link haskellCharacter Characterhi! link haskellStatement Statementhi! link haskellInclude Includehi! link haskellOperator Operator"hi! hsVarSym cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsConSym cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsLabel cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsDelimiter cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsSpecialChar cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! link hsSpecialCharError DiagnosticError"hi! hsString cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsCharacter cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsNumber cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsFloat cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsModule cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsImport cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsImportModuleName cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsImportMod cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsLineComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsBlockComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsImportList cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsImportGroup cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsTypedef cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsInfix cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsStructure cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsNewtypedef cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsTypeFam cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsStatement cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsConditional cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsPragma cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsOperator cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsLiterateComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsComment cterm=NONE ctermbg=NONE ctermfg=59 gui=NONE guifg=#575757"hi! hsBoolean cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsType cterm=NONE ctermbg=NONE ctermfg=8 gui=NONE guifg=#747369"hi! hsMaybe cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsEnumConst cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! hsOrdering cterm=NONE ctermbg=NONE ctermfg=15 gui=NONE guifg=#969896"hi! link hsDebug DiagnosticWarn"hi! link hsError DiagnosticErrorhi link IlluminatedWordText MatchParenhi link IlluminatedWordRead MatchParenhi link IlluminatedWordWrite MatchParenhi FlashMatch cterm=inverse ctermbg=0 ctermfg=13 gui=inverse guibg=#202020 guifg=#846488hi FlashCurrent cterm=inverse ctermbg=0 ctermfg=13 gui=inverse guibg=#202020 guifg=#846488hi FlashLabel cterm=inverse ctermbg=0 ctermfg=5 gui=inverse guibg=#202020 guifg=#cc99cchi FlashPrompt cterm=NONE ctermbg=13 ctermfg=0 gui=NONE guibg=#846488 guifg=#202020" hilight word under cursor" " toggle" nnoremap <leader>H :call MatchBoxHL()<cr>"" function! MatchBoxHL()" if exists('#matchboxhl')" hi! MatchBoxHL NONE" au! matchboxhl" augroup! matchboxhl" setl updatetime=4000" echo 'MatchBoxHL off'" else" setl updatetime=9" " highlight the word under cursor (CursorMoved is inperformant)" hi! MatchBoxHL cterm=NONE ctermbg=NONE ctermfg=6 gui=NONE guifg=#66cccc" augroup matchboxhl" au!" " au CursorMoved * silent! exe printf('match MatchBoxHL /\V\<%s\>/', escape(expand('<cword>'), '/\'))" au CursorHold * silent! exe printf('match MatchBoxHL /\V\<%s\>/', escape(expand('<cword>'), '/\'))" au CursorMoved * silent! match none" augroup end" echo 'MatchBoxHL on'" endif" endfunction"" " on by default" silent! call MatchBoxHL()
general {interval = 1colors = truecolor_good = "#b5bd68"color_degraded = "#de935f"color_bad = "#ff3334"}order += "volume master"#order += "ipv6"order += "cpu_usage"#order += "load"order += "disk /"order += "wireless _first_"order += "ethernet _first_"order += "run_watch VPN"order += "run_watch DHCP"order += "battery 0"order += "tztime local"wireless _first_ {format_up = "%quality%essid %ip"format_down = ""}ethernet _first_ {# if you use %speed, i3status requires root privilegesformat_up = "%speed %ip"format_down = ""}battery 0 {format = "%status %percentage %remaining"}run_watch DHCP {pidfile = "/var/run/dhclient*.pid"format = "%title"format_down = ""}run_watch VPN {pidfile = "/var/run/vpnc/pid"format = "%title"format_down = ""}tztime local {format = "%Y %m %d %H:%M "}cpu_usage {format = "%usage cpu"}#load {# format = "%1min"#}disk "/" {# format = "%percentage_used%total"format = "%used | %avail"}volume master {format = "%volume))"format_muted = "%volumex"device = "sysdefault"mixer = "Master"}
general {interval = 1colors = truecolor_good = "#b5bd68"color_degraded = "#de935f"color_bad = "#ff3334"}order += "volume master"#order += "ipv6"order += "cpu_usage"#order += "load"order += "disk /"order += "wireless _first_"order += "ethernet _first_"order += "run_watch VPN"order += "run_watch DHCP"order += "battery 0"order += "tztime local"wireless _first_ {format_up = "%quality%essid %ip"format_down = ""}ethernet _first_ {# if you use %speed, i3status requires root privilegesformat_up = "%speed %ip"format_down = ""}battery 0 {format = "%status %percentage %remaining"}run_watch DHCP {pidfile = "/var/run/dhclient*.pid"format = "%title"format_down = ""}run_watch VPN {pidfile = "/var/run/vpnc/pid"format = "%title"format_down = ""}tztime local {format = "%Y %m %d %H:%M "}cpu_usage {format = "%usage cpu"}#load {# format = "%1min"#}disk "/" {# format = "%percentage_used%total"format = "%used | %avail"}volume master {format = "%volume))"format_muted = "%volumex"device = "sysdefault"mixer = "Master"}
#!/bin/shset -exPREFIX=$(echo $1 | cut -d= -f 2)if [ -n "$PREFIX" ]thensed -i "s;^PREFIX.*;PREFIX = $PREFIX;g" Makefilefi
#!/usr/bin/env perl## Copyright (C) 2018-2021 James Murphy, Falko Galperin# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to play youtube videos from your clipboard using mpvuse strict;use warnings;use utf8;use Data::Validate::URI;my $signal = $ENV{signal} || 1;my $notify_i3bar = "pkill -RTMIN+$signal i3blocks";my $string = qx/xclip -out/;$string =~ s/[';\\]//g; # remove characters that can cause i3-msg to crashmy $uriValidator = new Data::Validate::URI();my $BLOCK_BUTTON = $ENV{BLOCK_BUTTON} || 0;my $PLAYING_COLOR = $ENV{PLAYING_COLOR} || "red";my $NOT_PLAYING_COLOR = $ENV{PLAYING_COLOR} || "white";my $USER = $ENV{USER};my $i3cmd = "";my $i3cmdexitstatus = 0;if ($uriValidator->is_web_uri($string) or $BLOCK_BUTTON == 3) {if ($BLOCK_BUTTON == 1) {$i3cmd = "exec mpv --ytdl --tls-verify '$string' && $notify_i3bar";} elsif ($BLOCK_BUTTON == 2) {$i3cmd = "exec mpv --ytdl --tls-verify --ytdl-format=bestaudio '$string' && $notify_i3bar";} elsif ($BLOCK_BUTTON == 3) {$i3cmd = "exec killall -u $USER mpv && $notify_i3bar";}system("i3-msg", "-q", $i3cmd);# i3-msg may return before mpv has startedsleep(.1);}my $color;if (system("pgrep -x mpv 2>&1 1>/dev/null") == 0) {$color = $PLAYING_COLOR;} else {$color = $NOT_PLAYING_COLOR;}binmode(STDOUT, ":utf8");print("<span color='$color'>\x{f16a}</span>\n");print("<span color='$color'>\x{f16a}</span>\n");
#!/usr/bin/env perl## Copyright (C) 2018-2021 James Murphy, Falko Galperin# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to play youtube videos from your clipboard using mpvuse strict;use warnings;use utf8;use Data::Validate::URI;my $signal = $ENV{signal} || 1;my $notify_i3bar = "pkill -RTMIN+$signal i3blocks";my $string = qx/xclip -out/;$string =~ s/[';\\]//g; # remove characters that can cause i3-msg to crashmy $uriValidator = new Data::Validate::URI();my $BLOCK_BUTTON = $ENV{BLOCK_BUTTON} || 0;my $PLAYING_COLOR = $ENV{PLAYING_COLOR} || "red";my $NOT_PLAYING_COLOR = $ENV{PLAYING_COLOR} || "white";my $USER = $ENV{USER};my $i3cmd = "";my $i3cmdexitstatus = 0;if ($uriValidator->is_web_uri($string) or $BLOCK_BUTTON == 3) {if ($BLOCK_BUTTON == 1) {$i3cmd = "exec mpv --ytdl --tls-verify '$string' && $notify_i3bar";} elsif ($BLOCK_BUTTON == 2) {$i3cmd = "exec mpv --ytdl --tls-verify --ytdl-format=bestaudio '$string' && $notify_i3bar";} elsif ($BLOCK_BUTTON == 3) {$i3cmd = "exec killall -u $USER mpv && $notify_i3bar";}system("i3-msg", "-q", $i3cmd);# i3-msg may return before mpv has startedsleep(.1);}my $color;if (system("pgrep -x mpv 2>&1 1>/dev/null") == 0) {$color = $PLAYING_COLOR;} else {$color = $NOT_PLAYING_COLOR;}binmode(STDOUT, ":utf8");print("<span color='$color'>\x{f16a}</span>\n");print("<span color='$color'>\x{f16a}</span>\n");
#!/usr/bin/env sh# This script is supposed to be used as an i3blocks persistent blocklet.# It outputs current keyboard layout, then waits for it to change in an infinite loop.# Requires `xkb-switch` utility. Should work in any *sh.# Written by skidnik <skidnik@gmail.com>## Defaults:font=${font:-monospace}font_weight=${font_weight:-bold}while :do# Output current layout:xkb-switch -p | awk -v font="$font" -v font_weight="$font_weight" '{print "<span font_family=\""font"\" font_weight=\""font_weight"\">"toupper($0)"</span>"}' || sleep 1# Wait for layout change:xkb-switch -wdone
#!/usr/bin/env sh# This script is supposed to be used as an i3blocks persistent blocklet.# It outputs current keyboard layout, then waits for it to change in an infinite loop.# Requires `xkb-switch` utility. Should work in any *sh.# Written by skidnik <skidnik@gmail.com>## Defaults:font=${font:-monospace}font_weight=${font_weight:-bold}while :do# Output current layout:xkb-switch -p | awk -v font="$font" -v font_weight="$font_weight" '{print "<span font_family=\""font"\" font_weight=\""font_weight"\">"toupper($0)"</span>"}' || sleep 1# Wait for layout change:xkb-switch -wdone
#!/usr/bin/env bash## i3blocks blocklet script to display wifi signal in dBmif [[ -z "$IFACE" ]] ; thenIFACE="${BLOCK_INSTANCE:-wlan0}"fiUSE_PERCENT=${USE_PERCENT:-0}IW=$(which iw || echo "/sbin/iw")if [[ ! -x $IW ]]; thenecho "No iw binary was found on the system." 1>2exit 1fiwhile getopts p opt; docase "$opt" inp) USE_PERCENT=1 ;;esacdonedbm=$($IW dev "$IFACE" link | grep 'dBm$' | grep -Eoe '-[0-9]{2}')[[ -n "$dbm" ]] || exit 1if [[ $USE_PERCENT -eq 0 ]]; thenecho "$dbm" dBmecho "$dbm"elseif [[ "$dbm" -le -100 ]]; thenquality=0elif [[ $dbm -ge -50 ]]; thenquality=100elsequality=$((2 * (dbm + 100)))fiecho "$quality%"echo "$quality%"fiif [[ $dbm -ge -55 ]]; thenecho "#00FF00"elif [[ $dbm -ge -60 ]]; thenecho "#CCFF00"elif [[ $dbm -ge -70 ]]; thenecho "#FFFF00"elif [[ $dbm -ge -80 ]]; thenecho "#FFAA00"elseecho "#FF0000"fi
#!/usr/bin/env bash## i3blocks blocklet script to display wifi signal in dBmif [[ -z "$IFACE" ]] ; thenIFACE="${BLOCK_INSTANCE:-wlan0}"fiUSE_PERCENT=${USE_PERCENT:-0}IW=$(which iw || echo "/sbin/iw")if [[ ! -x $IW ]]; thenecho "No iw binary was found on the system." 1>2exit 1fiwhile getopts p opt; docase "$opt" inp) USE_PERCENT=1 ;;esacdonedbm=$($IW dev "$IFACE" link | grep 'dBm$' | grep -Eoe '-[0-9]{2}')[[ -n "$dbm" ]] || exit 1if [[ $USE_PERCENT -eq 0 ]]; thenecho "$dbm" dBmecho "$dbm"elseif [[ "$dbm" -le -100 ]]; thenquality=0elif [[ $dbm -ge -50 ]]; thenquality=100elsequality=$((2 * (dbm + 100)))fiecho "$quality%"echo "$quality%"fiif [[ $dbm -ge -55 ]]; thenecho "#00FF00"elif [[ $dbm -ge -60 ]]; thenecho "#CCFF00"elif [[ $dbm -ge -70 ]]; thenecho "#FFFF00"elif [[ $dbm -ge -80 ]]; thenecho "#FFAA00"elseecho "#FF0000"fi
#!/bin/bash# Initialize outputOUTPUT=""NUMBER=0# Get all network interfaces (excluding loopback)mapfile -t INTERFACES < <(ip -o link show | awk -F': ' '{print $2}' | grep -v '^lo$')# Loop through interfacesfor DEVICE in "${INTERFACES[@]}"; do# Check if interface is UPif ! ip link show "$DEVICE" | grep -q "state UP"; thencontinuefi# Get IP addressIP=$(ip -4 addr show "$DEVICE" | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -n 1)# Skip if no IP assignedif [[ -z "$IP" ]]; thencontinuefi# Add separator for multiple connectionsif [ "$NUMBER" -gt 0 ]; thenOUTPUT+="<span color='#AEAEAE'> </span>"fi((NUMBER++))# Determine interface typeTYPE="ethernet"if [[ -L "/sys/class/net/$DEVICE/phy80211" ]] || [[ -d "/sys/class/net/$DEVICE/wireless" ]]; thenTYPE="wifi"fiSSID=""SIGNAL=""if [ "$TYPE" == "wifi" ]; then# Get SSIDSSID=$(iw dev "$DEVICE" info 2>/dev/null | grep ssid | awk '{print $2}')# Try Method 1: iwif [[ -z "$SIGNAL" ]]; thenWIFI_LINK=$(iw dev "$DEVICE" link 2>/dev/null)if [[ "$WIFI_LINK" =~ signal:\ ([+-]?[0-9]+) ]]; thenSIGNAL_DBM="${BASH_REMATCH[1]}"SIGNAL=$((2 * (SIGNAL_DBM + 100)))[[ "$SIGNAL" -lt 0 ]] && SIGNAL=0[[ "$SIGNAL" -gt 100 ]] && SIGNAL=100fifi# Try Method 3: iwdif [[ -z "$SIGNAL" ]] && command -v iwctl &> /dev/null; thenWIFI_LINK=$(iwctl station "$DEVICE" show 2>/dev/null)if [[ "$WIFI_LINK" =~ RSSI[[:space:]]+(-?[0-9]+) ]]; thenSIGNAL_DBM="${BASH_REMATCH[1]}"SIGNAL=$((2 * (SIGNAL_DBM + 100)))[[ "$SIGNAL" -lt 0 ]] && SIGNAL=0[[ "$SIGNAL" -gt 100 ]] && SIGNAL=100fifi# Try Method 2: NetworkManagerif [[ -z "$SIGNAL" ]] && command -v nmcli &> /dev/null; thenSIGNAL=$(nmcli -t -f DEVICE,SIGNAL dev wifi 2>/dev/null | grep "^$DEVICE:" | cut -d':' -f2)fifi# Define colors based on signal strengthif [[ -z "$SIGNAL" ]]; thenCOLOR="#AEAEAE"BAR="☵"elseif [ "$SIGNAL" -ge 90 ]; thenBAR="☰"COLOR="#00FF00"elif [ "$SIGNAL" -ge 70 ]; thenBAR="☱"COLOR="#AEFF00"elif [ "$SIGNAL" -ge 50 ]; thenBAR="☳"COLOR="#DDFF00"elif [ "$SIGNAL" -ge 30 ]; thenBAR="☷"COLOR="#FFDD00"elif [ "$SIGNAL" -ge 10 ]; thenBAR="⚏"COLOR="#FFAE00"elseBAR="⚋"COLOR="#FF0000"fifiECHO=""if [[ -n "$SSID" ]]; thenECHO+="$SSID "fiECHO+="$BAR $IP"OUTPUT+="<span color='$COLOR'>$ECHO</span>"doneecho "$OUTPUT"exit 0
#!/bin/bash# Initialize outputOUTPUT=""NUMBER=0# Get all network interfaces (excluding loopback)mapfile -t INTERFACES < <(ip -o link show | awk -F': ' '{print $2}' | grep -v '^lo$')# Loop through interfacesfor DEVICE in "${INTERFACES[@]}"; do# Check if interface is UPif ! ip link show "$DEVICE" | grep -q "state UP"; thencontinuefi# Get IP addressIP=$(ip -4 addr show "$DEVICE" | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -n 1)# Skip if no IP assignedif [[ -z "$IP" ]]; thencontinuefi# Add separator for multiple connectionsif [ "$NUMBER" -gt 0 ]; thenOUTPUT+="<span color='#AEAEAE'> </span>"fi((NUMBER++))# Determine interface typeTYPE="ethernet"if [[ -L "/sys/class/net/$DEVICE/phy80211" ]] || [[ -d "/sys/class/net/$DEVICE/wireless" ]]; thenTYPE="wifi"fiSSID=""SIGNAL=""if [ "$TYPE" == "wifi" ]; then# Get SSIDSSID=$(iw dev "$DEVICE" info 2>/dev/null | grep ssid | awk '{print $2}')# Try Method 1: iwif [[ -z "$SIGNAL" ]]; thenWIFI_LINK=$(iw dev "$DEVICE" link 2>/dev/null)if [[ "$WIFI_LINK" =~ signal:\ ([+-]?[0-9]+) ]]; thenSIGNAL_DBM="${BASH_REMATCH[1]}"SIGNAL=$((2 * (SIGNAL_DBM + 100)))[[ "$SIGNAL" -lt 0 ]] && SIGNAL=0[[ "$SIGNAL" -gt 100 ]] && SIGNAL=100fifi# Try Method 3: iwdif [[ -z "$SIGNAL" ]] && command -v iwctl &> /dev/null; thenWIFI_LINK=$(iwctl station "$DEVICE" show 2>/dev/null)if [[ "$WIFI_LINK" =~ RSSI[[:space:]]+(-?[0-9]+) ]]; thenSIGNAL_DBM="${BASH_REMATCH[1]}"SIGNAL=$((2 * (SIGNAL_DBM + 100)))[[ "$SIGNAL" -lt 0 ]] && SIGNAL=0[[ "$SIGNAL" -gt 100 ]] && SIGNAL=100fifi# Try Method 2: NetworkManagerif [[ -z "$SIGNAL" ]] && command -v nmcli &> /dev/null; thenSIGNAL=$(nmcli -t -f DEVICE,SIGNAL dev wifi 2>/dev/null | grep "^$DEVICE:" | cut -d':' -f2)fifi# Define colors based on signal strengthif [[ -z "$SIGNAL" ]]; thenCOLOR="#AEAEAE"BAR="☵"elseif [ "$SIGNAL" -ge 90 ]; thenBAR="☰"COLOR="#00FF00"elif [ "$SIGNAL" -ge 70 ]; thenBAR="☱"COLOR="#AEFF00"elif [ "$SIGNAL" -ge 50 ]; thenBAR="☳"COLOR="#DDFF00"elif [ "$SIGNAL" -ge 30 ]; thenBAR="☷"COLOR="#FFDD00"elif [ "$SIGNAL" -ge 10 ]; thenBAR="⚏"COLOR="#FFAE00"elseBAR="⚋"COLOR="#FF0000"fifiECHO=""if [[ -n "$SSID" ]]; thenECHO+="$SSID "fiECHO+="$BAR $IP"OUTPUT+="<span color='$COLOR'>$ECHO</span>"doneecho "$OUTPUT"exit 0
#!/usr/bin/env bash# Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------if [[ -z "$INTERFACE" ]] ; thenINTERFACE="${BLOCK_INSTANCE:-wlan0}"fi#------------------------------------------------------------------------COLOR_GE80=${COLOR_GE80:-#00FF00}COLOR_GE60=${COLOR_GE60:-#FFF600}COLOR_GE40=${COLOR_GE40:-#FFAE00}COLOR_LOWR=${COLOR_LOWR:-#FF0000}COLOR_DOWN=${COLOR_DOWN:-#FF0000}# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.[[ ! -d /sys/class/net/${INTERFACE}/wireless ]] && exit# If the wifi interface exists but no connection is active, "down" shall be displayed.if [[ "$(cat /sys/class/net/$INTERFACE/operstate)" = 'down' ]]; thenecho "down"echo "down"echo $COLOR_DOWNexitfi#------------------------------------------------------------------------QUALITY=$(iw dev ${INTERFACE} link | grep 'dBm$' | grep -Eoe '-[0-9]{2}' | awk '{print ($1 > -50 ? 100 :($1 < -100 ? 0 : ($1+100)*2))}')#------------------------------------------------------------------------echo $QUALITY% # full textecho $QUALITY% # short text# colorif [[ $QUALITY -ge 80 ]]; thenecho $COLOR_GE80elif [[ $QUALITY -ge 60 ]]; thenecho $COLOR_GE60elif [[ $QUALITY -ge 40 ]]; thenecho $COLOR_GE40elseecho $COLOR_LOWRfi
#!/usr/bin/env bash# Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------if [[ -z "$INTERFACE" ]] ; thenINTERFACE="${BLOCK_INSTANCE:-wlan0}"fi#------------------------------------------------------------------------COLOR_GE80=${COLOR_GE80:-#00FF00}COLOR_GE60=${COLOR_GE60:-#FFF600}COLOR_GE40=${COLOR_GE40:-#FFAE00}COLOR_LOWR=${COLOR_LOWR:-#FF0000}COLOR_DOWN=${COLOR_DOWN:-#FF0000}# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.[[ ! -d /sys/class/net/${INTERFACE}/wireless ]] && exit# If the wifi interface exists but no connection is active, "down" shall be displayed.if [[ "$(cat /sys/class/net/$INTERFACE/operstate)" = 'down' ]]; thenecho "down"echo "down"echo $COLOR_DOWNexitfi#------------------------------------------------------------------------QUALITY=$(iw dev ${INTERFACE} link | grep 'dBm$' | grep -Eoe '-[0-9]{2}' | awk '{print ($1 > -50 ? 100 :($1 < -100 ? 0 : ($1+100)*2))}')#------------------------------------------------------------------------echo $QUALITY% # full textecho $QUALITY% # short text# colorif [[ $QUALITY -ge 80 ]]; thenecho $COLOR_GE80elif [[ $QUALITY -ge 60 ]]; thenecho $COLOR_GE60elif [[ $QUALITY -ge 40 ]]; thenecho $COLOR_GE40elseecho $COLOR_LOWRfi
#!/usr/bin/env perl## Copyright 2021 Robert Unverzagt <robert.unverzagt@protonmail.com>## This program 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.## This program 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 this program. If not, see <https://www.gnu.org/licenses/>.use strict;use warnings;use JSON;use Data::Dumper;use Getopt::Long;# Default option values (default location is Portland, OR)my $lat = $ENV{LAT} || "45.52";my $lon = $ENV{LON} || "-122.70";sub help {print "Usage: weather_NOAA [-lat <latitude>] [-lon <longitude>]\n";print "-lat <latitude>: the latitude coordinate of your location\n";print "-lon <longitude>: the longitude coordinate of your location\n\n";print "NOTE: Only works in areas where NOAA publishes forecasts (namely the USA)\n";exit 0;}GetOptions( "help|h" => \&help,"lat=s" => \$lat,"lon=s" => \$lon,);# Use CURL to retrieve station ID and gridpointmy $json;{open( my $fh, 'curl -s https:\/\/api.weather.gov\/points\/'.$lat.','.$lon.' |') or die;local $/;$json = <$fh>;close $fh;}# Decode the json data into a perl native datatype, and extract the data we needmy $decoded = decode_json($json);# Detect errorif ($decoded->{"status"}){print "ERROR: ".$decoded->{'title'}."\n";print $decoded->{'detail'}."\n";die;}my $stationID = $decoded->{'properties'}->{'gridId'};my $Xcoord = $decoded->{'properties'}->{'gridX'};my $Ycoord = $decoded->{'properties'}->{'gridY'};# Use CURL to retrieve the forecast from NOAA{open( my $fh, 'curl -s https:\/\/api.weather.gov\/gridpoints\/'.$stationID.'\/'.$Xcoord.','.$Ycoord.'\/forecast\/hourly |') or die;local $/;$json = <$fh>;close $fh;}$decoded = decode_json($json);if ($decoded->{"status"}){print "ERROR: ".$decoded->{'title'}."\n";print $decoded->{'detail'}."\n";die;}# Extract just the forecast for the next hourmy $forecast = $decoded->{'properties'}->{'periods'}->[0];# Use this forecast data to construct the output stringprint $forecast->{'temperature'}."°".$forecast->{'temperatureUnit'}." ".$forecast->{'shortForecast'}."\n";
#!/usr/bin/env perl## Copyright 2021 Robert Unverzagt <robert.unverzagt@protonmail.com>## This program 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.## This program 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 this program. If not, see <https://www.gnu.org/licenses/>.use strict;use warnings;use JSON;use Data::Dumper;use Getopt::Long;# Default option values (default location is Portland, OR)my $lat = $ENV{LAT} || "45.52";my $lon = $ENV{LON} || "-122.70";sub help {print "Usage: weather_NOAA [-lat <latitude>] [-lon <longitude>]\n";print "-lat <latitude>: the latitude coordinate of your location\n";print "-lon <longitude>: the longitude coordinate of your location\n\n";print "NOTE: Only works in areas where NOAA publishes forecasts (namely the USA)\n";exit 0;}GetOptions( "help|h" => \&help,"lat=s" => \$lat,"lon=s" => \$lon,);# Use CURL to retrieve station ID and gridpointmy $json;{open( my $fh, 'curl -s https:\/\/api.weather.gov\/points\/'.$lat.','.$lon.' |') or die;local $/;$json = <$fh>;close $fh;}# Decode the json data into a perl native datatype, and extract the data we needmy $decoded = decode_json($json);# Detect errorif ($decoded->{"status"}){print "ERROR: ".$decoded->{'title'}."\n";print $decoded->{'detail'}."\n";die;}my $stationID = $decoded->{'properties'}->{'gridId'};my $Xcoord = $decoded->{'properties'}->{'gridX'};my $Ycoord = $decoded->{'properties'}->{'gridY'};# Use CURL to retrieve the forecast from NOAA{open( my $fh, 'curl -s https:\/\/api.weather.gov\/gridpoints\/'.$stationID.'\/'.$Xcoord.','.$Ycoord.'\/forecast\/hourly |') or die;local $/;$json = <$fh>;close $fh;}$decoded = decode_json($json);if ($decoded->{"status"}){print "ERROR: ".$decoded->{'title'}."\n";print $decoded->{'detail'}."\n";die;}# Extract just the forecast for the next hourmy $forecast = $decoded->{'properties'}->{'periods'}->[0];# Use this forecast data to construct the output stringprint $forecast->{'temperature'}."°".$forecast->{'temperatureUnit'}." ".$forecast->{'shortForecast'}."\n";
#!/usr/bin/env bash# Displays the default device, volume, and mute status for i3blocksset -aAUDIO_HIGH_SYMBOL=${AUDIO_HIGH_SYMBOL:-' '}AUDIO_MED_THRESH=${AUDIO_MED_THRESH:-50}AUDIO_MED_SYMBOL=${AUDIO_MED_SYMBOL:-' '}AUDIO_LOW_THRESH=${AUDIO_LOW_THRESH:-0}AUDIO_LOW_SYMBOL=${AUDIO_LOW_SYMBOL:-' '}AUDIO_MUTED_SYMBOL=${AUDIO_MUTED_SYMBOL:-' '}AUDIO_DELTA=${AUDIO_DELTA:-5}DEFAULT_COLOR=${DEFAULT_COLOR:-"#ffffff"}MUTED_COLOR=${MUTED_COLOR:-"#a0a0a0"}LONG_FORMAT=${LONG_FORMAT:-'${SYMB} ${VOL}% [${INDEX}:${NAME}]'}SHORT_FORMAT=${SHORT_FORMAT:-'${SYMB} ${VOL}% [${INDEX}]'}USE_ALSA_NAME=${USE_ALSA_NAME:-0}USE_DESCRIPTION=${USE_DESCRIPTION:-0}SUBSCRIBE=${SUBSCRIBE:-0}MIXER=${MIXER:-""}SCONTROL=${SCONTROL:-""}while getopts F:Sf:adH:M:L:X:T:t:C:c:i:m:s:h opt; docase "$opt" inS) SUBSCRIBE=1 ;;F) LONG_FORMAT="$OPTARG" ;;f) SHORT_FORMAT="$OPTARG" ;;a) USE_ALSA_NAME=1 ;;d) USE_DESCRIPTION=1 ;;H) AUDIO_HIGH_SYMBOL="$OPTARG" ;;M) AUDIO_MED_SYMBOL="$OPTARG" ;;L) AUDIO_LOW_SYMBOL="$OPTARG" ;;X) AUDIO_MUTED_SYMBOL="$OPTARG" ;;T) AUDIO_MED_THRESH="$OPTARG" ;;t) AUDIO_LOW_THRESH="$OPTARG" ;;C) DEFAULT_COLOR="$OPTARG" ;;c) MUTED_COLOR="$OPTARG" ;;i) AUDIO_INTERVAL="$OPTARG" ;;m) MIXER="$OPTARG" ;;s) SCONTROL="$OPTARG" ;;h) printf \"Usage: volume-pulseaudio [-S] [-F format] [-f format] [-p] [-a|-d] [-H symb] [-M symb][-L symb] [-X symb] [-T thresh] [-t thresh] [-C color] [-c color] [-i inter][-m mixer] [-s scontrol] [-j] [-h]Options:-F, -f\tOutput format (-F long format, -f short format) to use, with exposed variables:\${SYMB}, \${VOL}, \${INDEX}, \${NAME}-S\tSubscribe to volume events (requires persistent block, always uses long format)-a\tUse ALSA name if possible-d\tUse device description instead of name if possible-H\tSymbol to use when audio level is high. Default: '$AUDIO_HIGH_SYMBOL'-M\tSymbol to use when audio level is medium. Default: '$AUDIO_MED_SYMBOL'-L\tSymbol to use when audio level is low. Default: '$AUDIO_LOW_SYMBOL'-X\tSymbol to use when audio is muted. Default: '$AUDIO_MUTED_SYMBOL'-T\tThreshold for medium audio level. Default: $AUDIO_MED_THRESH-t\tThreshold for low audio level. Default: $AUDIO_LOW_THRESH-C\tColor for non-muted audio. Default: $DEFAULT_COLOR-c\tColor for muted audio. Default: $MUTED_COLOR-i\tInterval size of volume increase/decrease. Default: $AUDIO_DELTA-m\tUse the given mixer.-s\tUse the given scontrol.-h\tShow this help text" && exit 0;;esacdoneif [[ -z "$MIXER" ]] ; thenMIXER="default"if amixer -D pulse info >/dev/null 2>&1 ; thenMIXER="pulse"fifiif [[ -z "$SCONTROL" ]] ; thenSCONTROL=$(amixer -D "$MIXER" scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1)fiCAPABILITY=$(amixer -D $MIXER get $SCONTROL | sed -n "s/ Capabilities:.*cvolume.*/Capture/p")function move_sinks_to_new_default {DEFAULT_SINK=$1pacmd list-sink-inputs | grep index: | grep -o '[0-9]\+' | while read SINKdopacmd move-sink-input $SINK $DEFAULT_SINKdone}function set_default_playback_device_next {inc=${1:-1}num_devices=$(pacmd list-sinks | grep -c index:)sink_arr=($(pacmd list-sinks | grep index: | grep -o '[0-9]\+'))default_sink_index=$(( $(pacmd list-sinks | grep index: | grep -no '*' | grep -o '^[0-9]\+') - 1 ))default_sink_index=$(( ($default_sink_index + $num_devices + $inc) % $num_devices ))default_sink=${sink_arr[$default_sink_index]}pacmd set-default-sink $default_sinkmove_sinks_to_new_default $default_sink}case "$BLOCK_BUTTON" in1) set_default_playback_device_next ;;2) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY toggle ;;3) set_default_playback_device_next -1 ;;4) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%+ ;;5) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%- ;;esacfunction print_format {if [[ $markup == "pango" ]] ; thenoutput="<span color=\"$2\">$1</span>"elseoutput=$1fiecho "$output" | envsubst '${SYMB}${VOL}${INDEX}${NAME}'}function print_block {ACTIVE=$(pacmd list-sinks | grep "state\: RUNNING" -B4 -A7 | grep "index:\|name:\|volume: \(front\|mono\)\|muted:")[[ -z "$ACTIVE" ]] && ACTIVE=$(pacmd list-sinks | grep "index:\|name:\|volume: \(front\|mono\)\|muted:" | grep -A3 '*')for name in INDEX NAME VOL MUTED; doread $namedone < <(echo "$ACTIVE")INDEX=$(echo "$INDEX" | grep -o '[0-9]\+')VOL=$(echo "$VOL" | grep -o "[0-9]*%" | head -1 )VOL="${VOL%?}"NAME=$(echo "$NAME" | sed \'s/.*<.*\.\(.*\)>.*/\1/; t;'\'s/.*<\(.*\)>.*/\1/; t;'\'s/.*/unknown/')if [[ $USE_ALSA_NAME == 1 ]] ; thenALSA_NAME=$(pacmd list-sinks |\awk '/^\s*\*/{f=1}/^\s*index:/{f=0}f' |\grep "alsa.name\|alsa.mixer_name" |\head -n1 |\sed 's/.*= "\(.*\)".*/\1/')NAME=${ALSA_NAME:-$NAME}elif [[ $USE_DESCRIPTION == 1 ]] ; thenDESCRIPTION=$(pacmd list-sinks |\awk '/^\s*\*/{f=1}/^\s*index:/{f=0}f' |\grep "device.description" |\head -n1 |\sed 's/.*= "\(.*\)".*/\1/')NAME=${DESCRIPTION:-$NAME}fiif [[ $MUTED =~ "no" ]] ; thenSYMB=$AUDIO_HIGH_SYMBOL[[ $VOL -le $AUDIO_MED_THRESH ]] && SYMB=$AUDIO_MED_SYMBOL[[ $VOL -le $AUDIO_LOW_THRESH ]] && SYMB=$AUDIO_LOW_SYMBOLCOLOR=$DEFAULT_COLORelseSYMB=$AUDIO_MUTED_SYMBOLCOLOR=$MUTED_COLORfiprint_format "$LONG_FORMAT" $COLORif [[ $SUBSCRIBE != 1 ]] ; thenprint_format "$SHORT_FORMAT" $COLORecho $COLORfi}print_blockif [[ $SUBSCRIBE == 1 ]] ; thenwhile read -r EVENT; doprint_blockdone < <(pactl subscribe | stdbuf -oL grep change)fi
#!/usr/bin/env bash# Displays the default device, volume, and mute status for i3blocksset -aAUDIO_HIGH_SYMBOL=${AUDIO_HIGH_SYMBOL:-' '}AUDIO_MED_THRESH=${AUDIO_MED_THRESH:-50}AUDIO_MED_SYMBOL=${AUDIO_MED_SYMBOL:-' '}AUDIO_LOW_THRESH=${AUDIO_LOW_THRESH:-0}AUDIO_LOW_SYMBOL=${AUDIO_LOW_SYMBOL:-' '}AUDIO_MUTED_SYMBOL=${AUDIO_MUTED_SYMBOL:-' '}AUDIO_DELTA=${AUDIO_DELTA:-5}DEFAULT_COLOR=${DEFAULT_COLOR:-"#ffffff"}MUTED_COLOR=${MUTED_COLOR:-"#a0a0a0"}LONG_FORMAT=${LONG_FORMAT:-'${SYMB} ${VOL}% [${INDEX}:${NAME}]'}SHORT_FORMAT=${SHORT_FORMAT:-'${SYMB} ${VOL}% [${INDEX}]'}USE_ALSA_NAME=${USE_ALSA_NAME:-0}USE_DESCRIPTION=${USE_DESCRIPTION:-0}SUBSCRIBE=${SUBSCRIBE:-0}MIXER=${MIXER:-""}SCONTROL=${SCONTROL:-""}while getopts F:Sf:adH:M:L:X:T:t:C:c:i:m:s:h opt; docase "$opt" inS) SUBSCRIBE=1 ;;F) LONG_FORMAT="$OPTARG" ;;f) SHORT_FORMAT="$OPTARG" ;;a) USE_ALSA_NAME=1 ;;d) USE_DESCRIPTION=1 ;;H) AUDIO_HIGH_SYMBOL="$OPTARG" ;;M) AUDIO_MED_SYMBOL="$OPTARG" ;;L) AUDIO_LOW_SYMBOL="$OPTARG" ;;X) AUDIO_MUTED_SYMBOL="$OPTARG" ;;T) AUDIO_MED_THRESH="$OPTARG" ;;t) AUDIO_LOW_THRESH="$OPTARG" ;;C) DEFAULT_COLOR="$OPTARG" ;;c) MUTED_COLOR="$OPTARG" ;;i) AUDIO_INTERVAL="$OPTARG" ;;m) MIXER="$OPTARG" ;;s) SCONTROL="$OPTARG" ;;h) printf \"Usage: volume-pulseaudio [-S] [-F format] [-f format] [-p] [-a|-d] [-H symb] [-M symb][-L symb] [-X symb] [-T thresh] [-t thresh] [-C color] [-c color] [-i inter][-m mixer] [-s scontrol] [-j] [-h]Options:-F, -f\tOutput format (-F long format, -f short format) to use, with exposed variables:\${SYMB}, \${VOL}, \${INDEX}, \${NAME}-S\tSubscribe to volume events (requires persistent block, always uses long format)-a\tUse ALSA name if possible-d\tUse device description instead of name if possible-H\tSymbol to use when audio level is high. Default: '$AUDIO_HIGH_SYMBOL'-M\tSymbol to use when audio level is medium. Default: '$AUDIO_MED_SYMBOL'-L\tSymbol to use when audio level is low. Default: '$AUDIO_LOW_SYMBOL'-X\tSymbol to use when audio is muted. Default: '$AUDIO_MUTED_SYMBOL'-T\tThreshold for medium audio level. Default: $AUDIO_MED_THRESH-t\tThreshold for low audio level. Default: $AUDIO_LOW_THRESH-C\tColor for non-muted audio. Default: $DEFAULT_COLOR-c\tColor for muted audio. Default: $MUTED_COLOR-i\tInterval size of volume increase/decrease. Default: $AUDIO_DELTA-m\tUse the given mixer.-s\tUse the given scontrol.-h\tShow this help text" && exit 0;;esacdoneif [[ -z "$MIXER" ]] ; thenMIXER="default"if amixer -D pulse info >/dev/null 2>&1 ; thenMIXER="pulse"fifiif [[ -z "$SCONTROL" ]] ; thenSCONTROL=$(amixer -D "$MIXER" scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1)fiCAPABILITY=$(amixer -D $MIXER get $SCONTROL | sed -n "s/ Capabilities:.*cvolume.*/Capture/p")function move_sinks_to_new_default {DEFAULT_SINK=$1pacmd list-sink-inputs | grep index: | grep -o '[0-9]\+' | while read SINKdopacmd move-sink-input $SINK $DEFAULT_SINKdone}function set_default_playback_device_next {inc=${1:-1}num_devices=$(pacmd list-sinks | grep -c index:)sink_arr=($(pacmd list-sinks | grep index: | grep -o '[0-9]\+'))default_sink_index=$(( $(pacmd list-sinks | grep index: | grep -no '*' | grep -o '^[0-9]\+') - 1 ))default_sink_index=$(( ($default_sink_index + $num_devices + $inc) % $num_devices ))default_sink=${sink_arr[$default_sink_index]}pacmd set-default-sink $default_sinkmove_sinks_to_new_default $default_sink}case "$BLOCK_BUTTON" in1) set_default_playback_device_next ;;2) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY toggle ;;3) set_default_playback_device_next -1 ;;4) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%+ ;;5) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%- ;;esacfunction print_format {if [[ $markup == "pango" ]] ; thenoutput="<span color=\"$2\">$1</span>"elseoutput=$1fiecho "$output" | envsubst '${SYMB}${VOL}${INDEX}${NAME}'}function print_block {ACTIVE=$(pacmd list-sinks | grep "state\: RUNNING" -B4 -A7 | grep "index:\|name:\|volume: \(front\|mono\)\|muted:")[[ -z "$ACTIVE" ]] && ACTIVE=$(pacmd list-sinks | grep "index:\|name:\|volume: \(front\|mono\)\|muted:" | grep -A3 '*')for name in INDEX NAME VOL MUTED; doread $namedone < <(echo "$ACTIVE")INDEX=$(echo "$INDEX" | grep -o '[0-9]\+')VOL=$(echo "$VOL" | grep -o "[0-9]*%" | head -1 )VOL="${VOL%?}"NAME=$(echo "$NAME" | sed \'s/.*<.*\.\(.*\)>.*/\1/; t;'\'s/.*<\(.*\)>.*/\1/; t;'\'s/.*/unknown/')if [[ $USE_ALSA_NAME == 1 ]] ; thenALSA_NAME=$(pacmd list-sinks |\awk '/^\s*\*/{f=1}/^\s*index:/{f=0}f' |\grep "alsa.name\|alsa.mixer_name" |\head -n1 |\sed 's/.*= "\(.*\)".*/\1/')NAME=${ALSA_NAME:-$NAME}elif [[ $USE_DESCRIPTION == 1 ]] ; thenDESCRIPTION=$(pacmd list-sinks |\awk '/^\s*\*/{f=1}/^\s*index:/{f=0}f' |\grep "device.description" |\head -n1 |\sed 's/.*= "\(.*\)".*/\1/')NAME=${DESCRIPTION:-$NAME}fiif [[ $MUTED =~ "no" ]] ; thenSYMB=$AUDIO_HIGH_SYMBOL[[ $VOL -le $AUDIO_MED_THRESH ]] && SYMB=$AUDIO_MED_SYMBOL[[ $VOL -le $AUDIO_LOW_THRESH ]] && SYMB=$AUDIO_LOW_SYMBOLCOLOR=$DEFAULT_COLORelseSYMB=$AUDIO_MUTED_SYMBOLCOLOR=$MUTED_COLORfiprint_format "$LONG_FORMAT" $COLORif [[ $SUBSCRIBE != 1 ]] ; thenprint_format "$SHORT_FORMAT" $COLORecho $COLORfi}print_blockif [[ $SUBSCRIBE == 1 ]] ; thenwhile read -r EVENT; doprint_blockdone < <(pactl subscribe | stdbuf -oL grep change)fi
#!/bin/bash# Displays the default device, volume, and mute status for i3blocksset -aAUDIO_HIGH_SYMBOL=${AUDIO_HIGH_SYMBOL:-' '}AUDIO_MED_THRESH=${AUDIO_MED_THRESH:-50}AUDIO_MED_SYMBOL=${AUDIO_MED_SYMBOL:-' '}AUDIO_LOW_THRESH=${AUDIO_LOW_THRESH:-0}AUDIO_LOW_SYMBOL=${AUDIO_LOW_SYMBOL:-' '}AUDIO_MUTED_SYMBOL=${AUDIO_MUTED_SYMBOL:-' '}AUDIO_DELTA=${AUDIO_DELTA:-5}DEFAULT_COLOR=${DEFAULT_COLOR:-"#ffffff"}MUTED_COLOR=${MUTED_COLOR:-"#a0a0a0"}LONG_FORMAT=${LONG_FORMAT:-'${SYMB} ${VOL}% [${INDEX}:${NAME}]'}SHORT_FORMAT=${SHORT_FORMAT:-'${SYMB} ${VOL}% [${INDEX}]'}USE_ALSA_NAME=${USE_ALSA_NAME:-0}USE_DESCRIPTION=${USE_DESCRIPTION:-0}SUBSCRIBE=${SUBSCRIBE:-0}MIXER=${MIXER:-""}SCONTROL=${SCONTROL:-""}while getopts F:Sf:adH:M:L:X:T:t:C:c:i:m:s:h opt; docase "$opt" inS) SUBSCRIBE=1 ;;F) LONG_FORMAT="$OPTARG" ;;f) SHORT_FORMAT="$OPTARG" ;;a) USE_ALSA_NAME=1 ;;d) USE_DESCRIPTION=1 ;;H) AUDIO_HIGH_SYMBOL="$OPTARG" ;;M) AUDIO_MED_SYMBOL="$OPTARG" ;;L) AUDIO_LOW_SYMBOL="$OPTARG" ;;X) AUDIO_MUTED_SYMBOL="$OPTARG" ;;T) AUDIO_MED_THRESH="$OPTARG" ;;t) AUDIO_LOW_THRESH="$OPTARG" ;;C) DEFAULT_COLOR="$OPTARG" ;;c) MUTED_COLOR="$OPTARG" ;;i) AUDIO_INTERVAL="$OPTARG" ;;m) MIXER="$OPTARG" ;;s) SCONTROL="$OPTARG" ;;h) printf \"Usage: volume-pulseaudio [-S] [-F format] [-f format] [-p] [-a|-d] [-H symb] [-M symb][-L symb] [-X symb] [-T thresh] [-t thresh] [-C color] [-c color] [-i inter][-m mixer] [-s scontrol] [-h]Options:-F, -f\tOutput format (-F long format, -f short format) to use, with exposed variables:\${SYMB}, \${VOL}, \${INDEX}, \${NAME}-S\tSubscribe to volume events (requires persistent block, always uses long format)-a\tUse ALSA name if possible-d\tUse device description instead of name if possible-H\tSymbol to use when audio level is high. Default: '$AUDIO_HIGH_SYMBOL'-M\tSymbol to use when audio level is medium. Default: '$AUDIO_MED_SYMBOL'-L\tSymbol to use when audio level is low. Default: '$AUDIO_LOW_SYMBOL'-X\tSymbol to use when audio is muted. Default: '$AUDIO_MUTED_SYMBOL'-T\tThreshold for medium audio level. Default: $AUDIO_MED_THRESH-t\tThreshold for low audio level. Default: $AUDIO_LOW_THRESH-C\tColor for non-muted audio. Default: $DEFAULT_COLOR-c\tColor for muted audio. Default: $MUTED_COLOR-i\tInterval size of volume increase/decrease. Default: $AUDIO_DELTA-m\tUse the given mixer.-s\tUse the given scontrol.-h\tShow this help text" && exit 0;;esacdoneif [[ -z "$MIXER" ]] ; thenMIXER="default"if amixer -D pulse info >/dev/null 2>&1 ; thenMIXER="pulse"fifiif [[ -z "$SCONTROL" ]] ; thenSCONTROL=$(amixer -D "$MIXER" scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1)fiCAPABILITY=$(amixer -D $MIXER get $SCONTROL | sed -n "s/ Capabilities:.*cvolume.*/Capture/p")function move_sinks_to_new_default {DEFAULT_SINK=$1pactl list sink-inputs | grep 'Sink Input #' | grep -o '[0-9]\+' | while read SINKdopactl move-sink-input $SINK $DEFAULT_SINKdone}function set_default_playback_device_next {inc=${1:-1}num_devices=$(pactl list sinks | grep -c Name:)sink_arr=($(pactl list sinks | grep Name: | sed -r 's/\s+Name: (.+)/\1/'))default_sink=$(pactl get-default-sink)default_sink_index=$(for i in "${!sink_arr[@]}"; do if [[ "$default_sink" = "${sink_arr[$i]}" ]]; then echo "$i"; fi done)default_sink_index=$(( ($default_sink_index + $num_devices + $inc) % $num_devices ))default_sink=${sink_arr[$default_sink_index]}pactl set-default-sink $default_sinkmove_sinks_to_new_default $default_sink}case "$BLOCK_BUTTON" in1) set_default_playback_device_next ;;2) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY toggle ;;3) set_default_playback_device_next -1 ;;4) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%+ ;;5) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%- ;;esacfunction print_format {echo "$1" | envsubst '${SYMB}${VOL}${INDEX}${NAME}'}function print_block {ACTIVE="$(pactl list sinks | grep "State\: RUNNING" -B4 -A55)"if [[ $ACTIVE = "" ]] ; thenACTIVE="$(pactl list sinks | grep "$(pactl get-default-sink)" -B4 -A55)"fiACTIVE="$(echo "$ACTIVE" | grep "Name:\|Volume: \(front-left\|mono\)\|Mute:\|api.alsa.pcm.card = \|node.nick = ")"for Name in NAME MUTED VOL INDEX NICK; doread $Namedone < <(echo "$ACTIVE")INDEX=$(echo "$INDEX" | grep -o '".*"' | sed 's/"//g')VOL=$(echo "$VOL" | grep -o "[0-9]*%" | head -1 )VOL="${VOL%?}"NAME=$(echo "$NICK" | grep -o '".*"' | sed 's/"//g')if [[ $USE_ALSA_NAME == 1 ]] ; thenALSA_NAME=$(pactl list sinks |\awk '/^\s*\*/{f=1}/^\s*index:/{f=0}f' |\grep "alsa.name\|alsa.mixer_name" |\head -n1 |\sed 's/.*= "\(.*\)".*/\1/')NAME=${ALSA_NAME:-$NAME}elif [[ $USE_DESCRIPTION == 1 ]] ; thenDESCRIPTION=$(pactl list sinks | grep "State\: RUNNING" -B4 -A55 | grep 'Description: ' | sed 's/^.*: //')NAME=${DESCRIPTION:-$NAME}fiif [[ $MUTED =~ "no" ]] ; thenSYMB=$AUDIO_HIGH_SYMBOL[[ $VOL -le $AUDIO_MED_THRESH ]] && SYMB=$AUDIO_MED_SYMBOL[[ $VOL -le $AUDIO_LOW_THRESH ]] && SYMB=$AUDIO_LOW_SYMBOLCOLOR=$DEFAULT_COLORelseSYMB=$AUDIO_MUTED_SYMBOLCOLOR=$MUTED_COLORfiif [[ $ACTIVE = "" ]] ; thenecho "Sound inactive"COLOR='#222225'fiif [[ $SUBSCRIBE == 1 ]] ; thenprint_format "$LONG_FORMAT"elseprint_format "$LONG_FORMAT"print_format "$SHORT_FORMAT"echo "$COLOR"fi}print_blockif [[ $SUBSCRIBE == 1 ]] ; thenwhile read -r EVENT; doprint_blockdone < <(pactl subscribe | stdbuf -oL grep change)fi
#if you prefer automatic updating[volume-pipewire]command=$SCRIPT_DIR/volume-pipewireinterval=persistSUBSCRIBE=1USE_ALSA_NAME=1#if you prefer updating only when signaled[volume-pipewire]command=$SCRIPT_DIR/volume-pipewireinterval=oncesignal=1USE_ALSA_NAME=1
# Before using this blockThis is a fork of the block volume-pulseaudio, that supports pipewire,pulseaudio, and alsa. This is achieved by using the tool pactl instead of pacmd.So hopefuly this should be the future of this block.# volume-pipewireDisplay the system volume andoptionally the default playback device and index.Offers controls for these via clicks/scrolling.Supports changing audiostreams that are already playing.# Dependenciespipewire-pulse, pipewire-alsa, pipewire-jack, alsa-utils, fontawesome (fonts-font-awesome package) for the speaker symbols# UsageLeft/right clicks change default playback device, middle click mutes, scrollingadjusts volume. If your keyboard has audio buttons, it is suggested to add thethe following to your i3 config```# Pipewire-pulsebindsym XF86AudioMute exec pactl set-sink-mute 0 togglebindsym XF86AudioMute --release exec pkill -RTMIN+1 i3blocksbindsym XF86AudioLowerVolume exec pactl set-sink-volume 0 -5%bindsym XF86AudioLowerVolume --release exec pkill -RTMIN+1 i3blocksbindsym XF86AudioRaiseVolume exec pactl set-sink-volume 0 +5%bindsym XF86AudioRaiseVolume --release exec pkill -RTMIN+1 i3blocks# Media player controlsbindsym XF86AudioPlay exec playerctl play-pausebindsym XF86AudioPause exec playerctl play-pausebindsym XF86AudioNext exec playerctl nextbindsym XF86AudioPrev exec playerctl previous```where the number `1` in `-RTMIN+1` can be replaced to another signal number,as long as it agrees what you put for `signal=` in your i3blocks config.The previous lines also assume your mixer is "pulse" and your scontrol is "Master".If yours are different, change them appropriately.Alternatively to using signals, you may use the `SUBSCRIBE=1` option in your config in order to have the blockautomatically respond to audio change events. This option requires `interval=persist`and always uses the `LONG_FORMAT`.# Config```INI[volume-pipewire]command=$SCRIPT_DIR/volume-pipewireinterval=oncesignal=1#MIXER=[determined automatically]#SCONTROL=[determined automatically]##exposed format variables: ${SYMB}, ${VOL}, ${INDEX}, ${NAME}#LONG_FORMAT="${SYMB} ${VOL}% [${INDEX}:${NAME}]"#SHORT_FORMAT="${SYMB} ${VOL}% [${INDEX}]"#AUDIO_HIGH_SYMBOL=' '#AUDIO_MED_THRESH=50#AUDIO_MED_SYMBOL=' '#AUDIO_LOW_THRESH=0#AUDIO_LOW_SYMBOL=' '#AUDIO_DELTA=5#DEFAULT_COLOR="#ffffff"#MUTED_COLOR="#a0a0a0"#USE_ALSA_NAME=0#USE_DESCRIPTION=0## SUBSCRIBE=1 requires interval=persist and always uses LONG_FORMAT#SUBSCRIBE=0```
GNU GENERAL PUBLIC LICENSEVersion 2, June 1991Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USAEveryone is permitted to copy and distribute verbatim copiesof this license document, but changing it is not allowed.PreambleThe licenses for most software are designed to take away yourfreedom to share and change it. By contrast, the GNU General PublicLicense is intended to guarantee your freedom to share and change freesoftware--to make sure the software is free for all its users. ThisGeneral Public License applies to most of the Free SoftwareFoundation's software and to any other program whose authors commit tousing it. (Some other Free Software Foundation software is covered bythe GNU Lesser General Public License instead.) You can apply it toyour programs, too.When we speak of free software, we are referring to freedom, notprice. Our General Public Licenses are designed to make sure that youhave the freedom to distribute copies of free software (and charge forthis service if you wish), that you receive source code or can get itif you want it, that you can change the software or use pieces of itin new free programs; and that you know you can do these things.To protect your rights, we need to make restrictions that forbidanyone to deny you these rights or to ask you to surrender the rights.These restrictions translate to certain responsibilities for you if youdistribute copies of the software, or if you modify it.For example, if you distribute copies of such a program, whethergratis or for a fee, you must give the recipients all the rights thatyou have. You must make sure that they, too, receive or can get thesource code. And you must show them these terms so they know theirrights.We protect your rights with two steps: (1) copyright the software, and(2) offer you this license which gives you legal permission to copy,distribute and/or modify the software.Also, for each author's protection and ours, we want to make certainthat everyone understands that there is no warranty for this freesoftware. If the software is modified by someone else and passed on, wewant its recipients to know that what they have is not the original, sothat any problems introduced by others will not reflect on the originalauthors' reputations.Finally, any free program is threatened constantly by softwarepatents. We wish to avoid the danger that redistributors of a freeprogram will individually obtain patent licenses, in effect making theprogram proprietary. To prevent this, we have made it clear that anypatent must be licensed for everyone's free use or not licensed at all.The precise terms and conditions for copying, distribution andmodification follow.GNU GENERAL PUBLIC LICENSETERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION0. This License applies to any program or other work which containsa notice placed by the copyright holder saying it may be distributedunder the terms of this General Public License. The "Program", below,refers to any such program or work, and a "work based on the Program"means either the Program or any derivative work under copyright law:that is to say, a work containing the Program or a portion of it,either verbatim or with modifications and/or translated into anotherlanguage. (Hereinafter, translation is included without limitation inthe term "modification".) Each licensee is addressed as "you".Activities other than copying, distribution and modification are notcovered by this License; they are outside its scope. The act ofrunning the Program is not restricted, and the output from the Programis covered only if its contents constitute a work based on theProgram (independent of having been made by running the Program).Whether that is true depends on what the Program does.1. You may copy and distribute verbatim copies of the Program'ssource code as you receive it, in any medium, provided that youconspicuously and appropriately publish on each copy an appropriatecopyright notice and disclaimer of warranty; keep intact all thenotices that refer to this License and to the absence of any warranty;and give any other recipients of the Program a copy of this Licensealong with the Program.You may charge a fee for the physical act of transferring a copy, andyou may at your option offer warranty protection in exchange for a fee.2. You may modify your copy or copies of the Program or any portionof it, thus forming a work based on the Program, and copy anddistribute such modifications or work under the terms of Section 1above, provided that you also meet all of these conditions:a) You must cause the modified files to carry prominent noticesstating that you changed the files and the date of any change.b) You must cause any work that you distribute or publish, that inwhole or in part contains or is derived from the Program or anypart thereof, to be licensed as a whole at no charge to all thirdparties under the terms of this License.c) If the modified program normally reads commands interactivelywhen run, you must cause it, when started running for suchinteractive use in the most ordinary way, to print or display anannouncement including an appropriate copyright notice and anotice that there is no warranty (or else, saying that you providea warranty) and that users may redistribute the program underthese conditions, and telling the user how to view a copy of thisLicense. (Exception: if the Program itself is interactive butdoes not normally print such an announcement, your work based onthe Program is not required to print an announcement.)These requirements apply to the modified work as a whole. Ifidentifiable sections of that work are not derived from the Program,and can be reasonably considered independent and separate works inthemselves, then this License, and its terms, do not apply to thosesections when you distribute them as separate works. But when youdistribute the same sections as part of a whole which is a work basedon the Program, the distribution of the whole must be on the terms ofthis License, whose permissions for other licensees extend to theentire whole, and thus to each and every part regardless of who wrote it.Thus, it is not the intent of this section to claim rights or contestyour rights to work written entirely by you; rather, the intent is toexercise the right to control the distribution of derivative orcollective works based on the Program.In addition, mere aggregation of another work not based on the Programwith the Program (or with a work based on the Program) on a volume ofa storage or distribution medium does not bring the other work underthe scope of this License.3. You may copy and distribute the Program (or a work based on it,under Section 2) in object code or executable form under the terms ofSections 1 and 2 above provided that you also do one of the following:a) Accompany it with the complete corresponding machine-readablesource code, which must be distributed under the terms of Sections1 and 2 above on a medium customarily used for software interchange; or,b) Accompany it with a written offer, valid for at least threeyears, to give any third party, for a charge no more than yourcost of physically performing source distribution, a completemachine-readable copy of the corresponding source code, to bedistributed under the terms of Sections 1 and 2 above on a mediumcustomarily used for software interchange; or,c) Accompany it with the information you received as to the offerto distribute corresponding source code. (This alternative isallowed only for noncommercial distribution and only if youreceived the program in object code or executable form with suchan offer, in accord with Subsection b above.)The source code for a work means the preferred form of the work formaking modifications to it. For an executable work, complete sourcecode means all the source code for all modules it contains, plus anyassociated interface definition files, plus the scripts used tocontrol compilation and installation of the executable. However, as aspecial exception, the source code distributed need not includeanything that is normally distributed (in either source or binaryform) with the major components (compiler, kernel, and so on) of theoperating system on which the executable runs, unless that componentitself accompanies the executable.If distribution of executable or object code is made by offeringaccess to copy from a designated place, then offering equivalentaccess to copy the source code from the same place counts asdistribution of the source code, even though third parties are notcompelled to copy the source along with the object code.4. You may not copy, modify, sublicense, or distribute the Programexcept as expressly provided under this License. Any attemptotherwise to copy, modify, sublicense or distribute the Program isvoid, and will automatically terminate your rights under this License.However, parties who have received copies, or rights, from you underthis License will not have their licenses terminated so long as suchparties remain in full compliance.5. You are not required to accept this License, since you have notsigned it. However, nothing else grants you permission to modify ordistribute the Program or its derivative works. These actions areprohibited by law if you do not accept this License. Therefore, bymodifying or distributing the Program (or any work based on theProgram), you indicate your acceptance of this License to do so, andall its terms and conditions for copying, distributing or modifyingthe Program or works based on it.6. Each time you redistribute the Program (or any work based on theProgram), the recipient automatically receives a license from theoriginal licensor to copy, distribute or modify the Program subject tothese terms and conditions. You may not impose any furtherrestrictions on the recipients' exercise of the rights granted herein.You are not responsible for enforcing compliance by third parties tothis License.7. If, as a consequence of a court judgment or allegation of patentinfringement or for any other reason (not limited to patent issues),conditions are imposed on you (whether by court order, agreement orotherwise) that contradict the conditions of this License, they do notexcuse you from the conditions of this License. If you cannotdistribute so as to satisfy simultaneously your obligations under thisLicense and any other pertinent obligations, then as a consequence youmay not distribute the Program at all. For example, if a patentlicense would not permit royalty-free redistribution of the Program byall those who receive copies directly or indirectly through you, thenthe only way you could satisfy both it and this License would be torefrain entirely from distribution of the Program.If any portion of this section is held invalid or unenforceable underany particular circumstance, the balance of the section is intended toapply and the section as a whole is intended to apply in othercircumstances.It is not the purpose of this section to induce you to infringe anypatents or other property right claims or to contest validity of anysuch claims; this section has the sole purpose of protecting theintegrity of the free software distribution system, which isimplemented by public license practices. Many people have madegenerous contributions to the wide range of software distributedthrough that system in reliance on consistent application of thatsystem; it is up to the author/donor to decide if he or she is willingto distribute software through any other system and a licensee cannotimpose that choice.This section is intended to make thoroughly clear what is believed tobe a consequence of the rest of this License.8. If the distribution and/or use of the Program is restricted incertain countries either by patents or by copyrighted interfaces, theoriginal copyright holder who places the Program under this Licensemay add an explicit geographical distribution limitation excludingthose countries, so that distribution is permitted only in or amongcountries not thus excluded. In such case, this License incorporatesthe limitation as if written in the body of this License.9. The Free Software Foundation may publish revised and/or new versionsof the General Public License from time to time. Such new versions willbe similar in spirit to the present version, but may differ in detail toaddress new problems or concerns.Each version is given a distinguishing version number. If the Programspecifies a version number of this License which applies to it and "anylater version", you have the option of following the terms and conditionseither of that version or of any later version published by the FreeSoftware Foundation. If the Program does not specify a version number ofthis License, you may choose any version ever published by the Free SoftwareFoundation.10. If you wish to incorporate parts of the Program into other freeprograms whose distribution conditions are different, write to the authorto ask for permission. For software which is copyrighted by the FreeSoftware Foundation, write to the Free Software Foundation; we sometimesmake exceptions for this. Our decision will be guided by the two goalsof preserving the free status of all derivatives of our free software andof promoting the sharing and reuse of software generally.NO WARRANTY11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTYFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHENOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIESPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSEDOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OFMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK ASTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THEPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,REPAIR OR CORRECTION.12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITINGWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/ORREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISINGOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITEDTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BYYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHERPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THEPOSSIBILITY OF SUCH DAMAGES.END OF TERMS AND CONDITIONSHow to Apply These Terms to Your New ProgramsIf you develop a new program, and you want it to be of the greatestpossible use to the public, the best way to achieve this is to make itfree software which everyone can redistribute and change under these terms.To do so, attach the following notices to the program. It is safestto attach them to the start of each source file to most effectivelyconvey the exclusion of warranty; and each file should have at leastthe "copyright" line and a pointer to where the full notice is found.{description}Copyright (C) {year} {fullname}This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Also add information on how to contact you by electronic and paper mail.If the program is interactive, make it output a short notice like thiswhen it starts in an interactive mode:Gnomovision version 69, Copyright (C) year name of authorGnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.This is free software, and you are welcome to redistribute itunder certain conditions; type `show c' for details.The hypothetical commands `show w' and `show c' should show the appropriateparts of the General Public License. Of course, the commands you use maybe called something other than `show w' and `show c'; they could even bemouse-clicks or menu items--whatever suits your program.You should also get your employer (if you work as a programmer) or yourschool, if any, to sign a "copyright disclaimer" for the program, ifnecessary. Here is a sample; alter the names:Yoyodyne, Inc., hereby disclaims all copyright interest in the program`Gnomovision' (which makes passes at compilers) written by James Hacker.{signature of Ty Coon}, 1 April 1989Ty Coon, President of ViceThis General Public License does not permit incorporating your program intoproprietary programs. If your program is a subroutine library, you mayconsider it more useful to permit linking proprietary applications with thelibrary. If this is what you want to do, use the GNU Lesser GeneralPublic License instead of this License.
#!/bin/bash# Displays the default device, volume, and mute status for i3blocksset -aAUDIO_HIGH_SYMBOL=${AUDIO_HIGH_SYMBOL:-' '}AUDIO_MED_THRESH=${AUDIO_MED_THRESH:-50}AUDIO_MED_SYMBOL=${AUDIO_MED_SYMBOL:-' '}AUDIO_LOW_THRESH=${AUDIO_LOW_THRESH:-0}AUDIO_LOW_SYMBOL=${AUDIO_LOW_SYMBOL:-' '}AUDIO_MUTED_SYMBOL=${AUDIO_MUTED_SYMBOL:-' '}AUDIO_DELTA=${AUDIO_DELTA:-5}DEFAULT_COLOR=${DEFAULT_COLOR:-"#ffffff"}MUTED_COLOR=${MUTED_COLOR:-"#a0a0a0"}LONG_FORMAT=${LONG_FORMAT:-'${SYMB} ${VOL}% [${INDEX}:${NAME}]'}SHORT_FORMAT=${SHORT_FORMAT:-'${SYMB} ${VOL}% [${INDEX}]'}USE_ALSA_NAME=${USE_ALSA_NAME:-0}USE_DESCRIPTION=${USE_DESCRIPTION:-0}SUBSCRIBE=${SUBSCRIBE:-0}MIXER=${MIXER:-""}SCONTROL=${SCONTROL:-""}while getopts F:Sf:adH:M:L:X:T:t:C:c:i:m:s:h opt; docase "$opt" inS) SUBSCRIBE=1 ;;F) LONG_FORMAT="$OPTARG" ;;f) SHORT_FORMAT="$OPTARG" ;;a) USE_ALSA_NAME=1 ;;d) USE_DESCRIPTION=1 ;;H) AUDIO_HIGH_SYMBOL="$OPTARG" ;;M) AUDIO_MED_SYMBOL="$OPTARG" ;;L) AUDIO_LOW_SYMBOL="$OPTARG" ;;X) AUDIO_MUTED_SYMBOL="$OPTARG" ;;T) AUDIO_MED_THRESH="$OPTARG" ;;t) AUDIO_LOW_THRESH="$OPTARG" ;;C) DEFAULT_COLOR="$OPTARG" ;;c) MUTED_COLOR="$OPTARG" ;;i) AUDIO_INTERVAL="$OPTARG" ;;m) MIXER="$OPTARG" ;;s) SCONTROL="$OPTARG" ;;h) printf \"Usage: volume-pulseaudio [-S] [-F format] [-f format] [-p] [-a|-d] [-H symb] [-M symb][-L symb] [-X symb] [-T thresh] [-t thresh] [-C color] [-c color] [-i inter][-m mixer] [-s scontrol] [-h]Options:-F, -f\tOutput format (-F long format, -f short format) to use, with exposed variables:\${SYMB}, \${VOL}, \${INDEX}, \${NAME}-S\tSubscribe to volume events (requires persistent block, always uses long format)-a\tUse ALSA name if possible-d\tUse device description instead of name if possible-H\tSymbol to use when audio level is high. Default: '$AUDIO_HIGH_SYMBOL'-M\tSymbol to use when audio level is medium. Default: '$AUDIO_MED_SYMBOL'-L\tSymbol to use when audio level is low. Default: '$AUDIO_LOW_SYMBOL'-X\tSymbol to use when audio is muted. Default: '$AUDIO_MUTED_SYMBOL'-T\tThreshold for medium audio level. Default: $AUDIO_MED_THRESH-t\tThreshold for low audio level. Default: $AUDIO_LOW_THRESH-C\tColor for non-muted audio. Default: $DEFAULT_COLOR-c\tColor for muted audio. Default: $MUTED_COLOR-i\tInterval size of volume increase/decrease. Default: $AUDIO_DELTA-m\tUse the given mixer.-s\tUse the given scontrol.-h\tShow this help text" && exit 0;;esacdoneif [[ -z "$MIXER" ]] ; thenMIXER="default"if amixer -D pulse info >/dev/null 2>&1 ; thenMIXER="pulse"fifiif [[ -z "$SCONTROL" ]] ; thenSCONTROL=$(amixer -D "$MIXER" scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1)fiCAPABILITY=$(amixer -D $MIXER get $SCONTROL | sed -n "s/ Capabilities:.*cvolume.*/Capture/p")function move_sinks_to_new_default {DEFAULT_SINK=$1pactl list sink-inputs | grep 'Sink Input #' | grep -o '[0-9]\+' | while read SINKdopactl move-sink-input $SINK $DEFAULT_SINKdone}function set_default_playback_device_next {inc=${1:-1}num_devices=$(pactl list sinks | grep -c Name:)sink_arr=($(pactl list sinks | grep Name: | sed -r 's/\s+Name: (.+)/\1/'))default_sink=$(pactl get-default-sink)default_sink_index=$(for i in "${!sink_arr[@]}"; do if [[ "$default_sink" = "${sink_arr[$i]}" ]]; then echo "$i"; fi done)default_sink_index=$(( ($default_sink_index + $num_devices + $inc) % $num_devices ))default_sink=${sink_arr[$default_sink_index]}pactl set-default-sink $default_sinkmove_sinks_to_new_default $default_sink}case "$BLOCK_BUTTON" in1) set_default_playback_device_next ;;2) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY toggle ;;3) set_default_playback_device_next -1 ;;4) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%+ ;;5) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%- ;;esacfunction print_format {echo "$1" | envsubst '${SYMB}${VOL}${INDEX}${NAME}'}function print_block {ACTIVE="$(pactl list sinks | grep "State\: RUNNING" -B4 -A55)"if [[ $ACTIVE = "" ]] ; thenACTIVE="$(pactl list sinks | grep "$(pactl get-default-sink)" -B4 -A55)"fiACTIVE="$(echo "$ACTIVE" | grep "Name:\|Volume: \(front-left\|mono\)\|Mute:\|api.alsa.pcm.card = \|node.nick = ")"for Name in NAME MUTED VOL INDEX NICK; doread $Namedone < <(echo "$ACTIVE")INDEX=$(echo "$INDEX" | grep -o '".*"' | sed 's/"//g')VOL=$(echo "$VOL" | grep -o "[0-9]*%" | head -1 )VOL="${VOL%?}"NAME=$(echo "$NICK" | grep -o '".*"' | sed 's/"//g')if [[ $USE_ALSA_NAME == 1 ]] ; thenALSA_NAME=$(pactl list sinks |\awk '/^\s*\*/{f=1}/^\s*index:/{f=0}f' |\grep "alsa.name\|alsa.mixer_name" |\head -n1 |\sed 's/.*= "\(.*\)".*/\1/')NAME=${ALSA_NAME:-$NAME}elif [[ $USE_DESCRIPTION == 1 ]] ; thenDESCRIPTION=$(pactl list sinks | grep "State\: RUNNING" -B4 -A55 | grep 'Description: ' | sed 's/^.*: //')NAME=${DESCRIPTION:-$NAME}fiif [[ $MUTED =~ "no" ]] ; thenSYMB=$AUDIO_HIGH_SYMBOL[[ $VOL -le $AUDIO_MED_THRESH ]] && SYMB=$AUDIO_MED_SYMBOL[[ $VOL -le $AUDIO_LOW_THRESH ]] && SYMB=$AUDIO_LOW_SYMBOLCOLOR=$DEFAULT_COLORelseSYMB=$AUDIO_MUTED_SYMBOLCOLOR=$MUTED_COLORfiif [[ $ACTIVE = "" ]] ; thenecho "Sound inactive"COLOR='#222225'fiif [[ $SUBSCRIBE == 1 ]] ; thenprint_format "$LONG_FORMAT"elseprint_format "$LONG_FORMAT"print_format "$SHORT_FORMAT"echo "$COLOR"fi}print_blockif [[ $SUBSCRIBE == 1 ]] ; thenwhile read -r EVENT; doprint_blockdone < <(pactl subscribe | stdbuf -oL grep change)fi
#if you prefer automatic updating[volume-pipewire]command=$SCRIPT_DIR/volume-pipewireinterval=persistSUBSCRIBE=1USE_ALSA_NAME=1#if you prefer updating only when signaled[volume-pipewire]command=$SCRIPT_DIR/volume-pipewireinterval=oncesignal=1USE_ALSA_NAME=1
# Before using this blockThis is a fork of the block volume-pulseaudio, that supports pipewire,pulseaudio, and alsa. This is achieved by using the tool pactl instead of pacmd.So hopefuly this should be the future of this block.# volume-pipewireDisplay the system volume andoptionally the default playback device and index.Offers controls for these via clicks/scrolling.Supports changing audiostreams that are already playing.# Dependenciespipewire-pulse, pipewire-alsa, pipewire-jack, alsa-utils, fontawesome (fonts-font-awesome package) for the speaker symbols# UsageLeft/right clicks change default playback device, middle click mutes, scrollingadjusts volume. If your keyboard has audio buttons, it is suggested to add thethe following to your i3 config```# Pipewire-pulsebindsym XF86AudioMute exec pactl set-sink-mute 0 togglebindsym XF86AudioMute --release exec pkill -RTMIN+1 i3blocksbindsym XF86AudioLowerVolume exec pactl set-sink-volume 0 -5%bindsym XF86AudioLowerVolume --release exec pkill -RTMIN+1 i3blocksbindsym XF86AudioRaiseVolume exec pactl set-sink-volume 0 +5%bindsym XF86AudioRaiseVolume --release exec pkill -RTMIN+1 i3blocks# Media player controlsbindsym XF86AudioPlay exec playerctl play-pausebindsym XF86AudioPause exec playerctl play-pausebindsym XF86AudioNext exec playerctl nextbindsym XF86AudioPrev exec playerctl previous```where the number `1` in `-RTMIN+1` can be replaced to another signal number,as long as it agrees what you put for `signal=` in your i3blocks config.The previous lines also assume your mixer is "pulse" and your scontrol is "Master".If yours are different, change them appropriately.Alternatively to using signals, you may use the `SUBSCRIBE=1` option in your config in order to have the blockautomatically respond to audio change events. This option requires `interval=persist`and always uses the `LONG_FORMAT`.# Config```INI[volume-pipewire]command=$SCRIPT_DIR/volume-pipewireinterval=oncesignal=1#MIXER=[determined automatically]#SCONTROL=[determined automatically]##exposed format variables: ${SYMB}, ${VOL}, ${INDEX}, ${NAME}#LONG_FORMAT="${SYMB} ${VOL}% [${INDEX}:${NAME}]"#SHORT_FORMAT="${SYMB} ${VOL}% [${INDEX}]"#AUDIO_HIGH_SYMBOL=' '#AUDIO_MED_THRESH=50#AUDIO_MED_SYMBOL=' '#AUDIO_LOW_THRESH=0#AUDIO_LOW_SYMBOL=' '#AUDIO_DELTA=5#DEFAULT_COLOR="#ffffff"#MUTED_COLOR="#a0a0a0"#USE_ALSA_NAME=0#USE_DESCRIPTION=0## SUBSCRIBE=1 requires interval=persist and always uses LONG_FORMAT#SUBSCRIBE=0```
GNU GENERAL PUBLIC LICENSEVersion 2, June 1991Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USAEveryone is permitted to copy and distribute verbatim copiesof this license document, but changing it is not allowed.PreambleThe licenses for most software are designed to take away yourfreedom to share and change it. By contrast, the GNU General PublicLicense is intended to guarantee your freedom to share and change freesoftware--to make sure the software is free for all its users. ThisGeneral Public License applies to most of the Free SoftwareFoundation's software and to any other program whose authors commit tousing it. (Some other Free Software Foundation software is covered bythe GNU Lesser General Public License instead.) You can apply it toyour programs, too.When we speak of free software, we are referring to freedom, notprice. Our General Public Licenses are designed to make sure that youhave the freedom to distribute copies of free software (and charge forthis service if you wish), that you receive source code or can get itif you want it, that you can change the software or use pieces of itin new free programs; and that you know you can do these things.To protect your rights, we need to make restrictions that forbidanyone to deny you these rights or to ask you to surrender the rights.These restrictions translate to certain responsibilities for you if youdistribute copies of the software, or if you modify it.For example, if you distribute copies of such a program, whethergratis or for a fee, you must give the recipients all the rights thatyou have. You must make sure that they, too, receive or can get thesource code. And you must show them these terms so they know theirrights.We protect your rights with two steps: (1) copyright the software, and(2) offer you this license which gives you legal permission to copy,distribute and/or modify the software.Also, for each author's protection and ours, we want to make certainthat everyone understands that there is no warranty for this freesoftware. If the software is modified by someone else and passed on, wewant its recipients to know that what they have is not the original, sothat any problems introduced by others will not reflect on the originalauthors' reputations.Finally, any free program is threatened constantly by softwarepatents. We wish to avoid the danger that redistributors of a freeprogram will individually obtain patent licenses, in effect making theprogram proprietary. To prevent this, we have made it clear that anypatent must be licensed for everyone's free use or not licensed at all.The precise terms and conditions for copying, distribution andmodification follow.GNU GENERAL PUBLIC LICENSETERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION0. This License applies to any program or other work which containsa notice placed by the copyright holder saying it may be distributedunder the terms of this General Public License. The "Program", below,refers to any such program or work, and a "work based on the Program"means either the Program or any derivative work under copyright law:that is to say, a work containing the Program or a portion of it,either verbatim or with modifications and/or translated into anotherlanguage. (Hereinafter, translation is included without limitation inthe term "modification".) Each licensee is addressed as "you".Activities other than copying, distribution and modification are notcovered by this License; they are outside its scope. The act ofrunning the Program is not restricted, and the output from the Programis covered only if its contents constitute a work based on theProgram (independent of having been made by running the Program).Whether that is true depends on what the Program does.1. You may copy and distribute verbatim copies of the Program'ssource code as you receive it, in any medium, provided that youconspicuously and appropriately publish on each copy an appropriatecopyright notice and disclaimer of warranty; keep intact all thenotices that refer to this License and to the absence of any warranty;and give any other recipients of the Program a copy of this Licensealong with the Program.You may charge a fee for the physical act of transferring a copy, andyou may at your option offer warranty protection in exchange for a fee.2. You may modify your copy or copies of the Program or any portionof it, thus forming a work based on the Program, and copy anddistribute such modifications or work under the terms of Section 1above, provided that you also meet all of these conditions:a) You must cause the modified files to carry prominent noticesstating that you changed the files and the date of any change.b) You must cause any work that you distribute or publish, that inwhole or in part contains or is derived from the Program or anypart thereof, to be licensed as a whole at no charge to all thirdparties under the terms of this License.c) If the modified program normally reads commands interactivelywhen run, you must cause it, when started running for suchinteractive use in the most ordinary way, to print or display anannouncement including an appropriate copyright notice and anotice that there is no warranty (or else, saying that you providea warranty) and that users may redistribute the program underthese conditions, and telling the user how to view a copy of thisLicense. (Exception: if the Program itself is interactive butdoes not normally print such an announcement, your work based onthe Program is not required to print an announcement.)These requirements apply to the modified work as a whole. Ifidentifiable sections of that work are not derived from the Program,and can be reasonably considered independent and separate works inthemselves, then this License, and its terms, do not apply to thosesections when you distribute them as separate works. But when youdistribute the same sections as part of a whole which is a work basedon the Program, the distribution of the whole must be on the terms ofthis License, whose permissions for other licensees extend to theentire whole, and thus to each and every part regardless of who wrote it.Thus, it is not the intent of this section to claim rights or contestyour rights to work written entirely by you; rather, the intent is toexercise the right to control the distribution of derivative orcollective works based on the Program.In addition, mere aggregation of another work not based on the Programwith the Program (or with a work based on the Program) on a volume ofa storage or distribution medium does not bring the other work underthe scope of this License.3. You may copy and distribute the Program (or a work based on it,under Section 2) in object code or executable form under the terms ofSections 1 and 2 above provided that you also do one of the following:a) Accompany it with the complete corresponding machine-readablesource code, which must be distributed under the terms of Sections1 and 2 above on a medium customarily used for software interchange; or,b) Accompany it with a written offer, valid for at least threeyears, to give any third party, for a charge no more than yourcost of physically performing source distribution, a completemachine-readable copy of the corresponding source code, to bedistributed under the terms of Sections 1 and 2 above on a mediumcustomarily used for software interchange; or,c) Accompany it with the information you received as to the offerto distribute corresponding source code. (This alternative isallowed only for noncommercial distribution and only if youreceived the program in object code or executable form with suchan offer, in accord with Subsection b above.)The source code for a work means the preferred form of the work formaking modifications to it. For an executable work, complete sourcecode means all the source code for all modules it contains, plus anyassociated interface definition files, plus the scripts used tocontrol compilation and installation of the executable. However, as aspecial exception, the source code distributed need not includeanything that is normally distributed (in either source or binaryform) with the major components (compiler, kernel, and so on) of theoperating system on which the executable runs, unless that componentitself accompanies the executable.If distribution of executable or object code is made by offeringaccess to copy from a designated place, then offering equivalentaccess to copy the source code from the same place counts asdistribution of the source code, even though third parties are notcompelled to copy the source along with the object code.4. You may not copy, modify, sublicense, or distribute the Programexcept as expressly provided under this License. Any attemptotherwise to copy, modify, sublicense or distribute the Program isvoid, and will automatically terminate your rights under this License.However, parties who have received copies, or rights, from you underthis License will not have their licenses terminated so long as suchparties remain in full compliance.5. You are not required to accept this License, since you have notsigned it. However, nothing else grants you permission to modify ordistribute the Program or its derivative works. These actions areprohibited by law if you do not accept this License. Therefore, bymodifying or distributing the Program (or any work based on theProgram), you indicate your acceptance of this License to do so, andall its terms and conditions for copying, distributing or modifyingthe Program or works based on it.6. Each time you redistribute the Program (or any work based on theProgram), the recipient automatically receives a license from theoriginal licensor to copy, distribute or modify the Program subject tothese terms and conditions. You may not impose any furtherrestrictions on the recipients' exercise of the rights granted herein.You are not responsible for enforcing compliance by third parties tothis License.7. If, as a consequence of a court judgment or allegation of patentinfringement or for any other reason (not limited to patent issues),conditions are imposed on you (whether by court order, agreement orotherwise) that contradict the conditions of this License, they do notexcuse you from the conditions of this License. If you cannotdistribute so as to satisfy simultaneously your obligations under thisLicense and any other pertinent obligations, then as a consequence youmay not distribute the Program at all. For example, if a patentlicense would not permit royalty-free redistribution of the Program byall those who receive copies directly or indirectly through you, thenthe only way you could satisfy both it and this License would be torefrain entirely from distribution of the Program.If any portion of this section is held invalid or unenforceable underany particular circumstance, the balance of the section is intended toapply and the section as a whole is intended to apply in othercircumstances.It is not the purpose of this section to induce you to infringe anypatents or other property right claims or to contest validity of anysuch claims; this section has the sole purpose of protecting theintegrity of the free software distribution system, which isimplemented by public license practices. Many people have madegenerous contributions to the wide range of software distributedthrough that system in reliance on consistent application of thatsystem; it is up to the author/donor to decide if he or she is willingto distribute software through any other system and a licensee cannotimpose that choice.This section is intended to make thoroughly clear what is believed tobe a consequence of the rest of this License.8. If the distribution and/or use of the Program is restricted incertain countries either by patents or by copyrighted interfaces, theoriginal copyright holder who places the Program under this Licensemay add an explicit geographical distribution limitation excludingthose countries, so that distribution is permitted only in or amongcountries not thus excluded. In such case, this License incorporatesthe limitation as if written in the body of this License.9. The Free Software Foundation may publish revised and/or new versionsof the General Public License from time to time. Such new versions willbe similar in spirit to the present version, but may differ in detail toaddress new problems or concerns.Each version is given a distinguishing version number. If the Programspecifies a version number of this License which applies to it and "anylater version", you have the option of following the terms and conditionseither of that version or of any later version published by the FreeSoftware Foundation. If the Program does not specify a version number ofthis License, you may choose any version ever published by the Free SoftwareFoundation.10. If you wish to incorporate parts of the Program into other freeprograms whose distribution conditions are different, write to the authorto ask for permission. For software which is copyrighted by the FreeSoftware Foundation, write to the Free Software Foundation; we sometimesmake exceptions for this. Our decision will be guided by the two goalsof preserving the free status of all derivatives of our free software andof promoting the sharing and reuse of software generally.NO WARRANTY11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTYFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHENOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIESPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSEDOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OFMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK ASTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THEPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,REPAIR OR CORRECTION.12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITINGWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/ORREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISINGOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITEDTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BYYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHERPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THEPOSSIBILITY OF SUCH DAMAGES.END OF TERMS AND CONDITIONSHow to Apply These Terms to Your New ProgramsIf you develop a new program, and you want it to be of the greatestpossible use to the public, the best way to achieve this is to make itfree software which everyone can redistribute and change under these terms.To do so, attach the following notices to the program. It is safestto attach them to the start of each source file to most effectivelyconvey the exclusion of warranty; and each file should have at leastthe "copyright" line and a pointer to where the full notice is found.{description}Copyright (C) {year} {fullname}This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Also add information on how to contact you by electronic and paper mail.If the program is interactive, make it output a short notice like thiswhen it starts in an interactive mode:Gnomovision version 69, Copyright (C) year name of authorGnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.This is free software, and you are welcome to redistribute itunder certain conditions; type `show c' for details.The hypothetical commands `show w' and `show c' should show the appropriateparts of the General Public License. Of course, the commands you use maybe called something other than `show w' and `show c'; they could even bemouse-clicks or menu items--whatever suits your program.You should also get your employer (if you work as a programmer) or yourschool, if any, to sign a "copyright disclaimer" for the program, ifnecessary. Here is a sample; alter the names:Yoyodyne, Inc., hereby disclaims all copyright interest in the program`Gnomovision' (which makes passes at compilers) written by James Hacker.{signature of Ty Coon}, 1 April 1989Ty Coon, President of ViceThis General Public License does not permit incorporating your program intoproprietary programs. If your program is a subroutine library, you mayconsider it more useful to permit linking proprietary applications with thelibrary. If this is what you want to do, use the GNU Lesser GeneralPublic License instead of this License.
#!/usr/bin/env bash# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------# The second parameter overrides the mixer selection# For PulseAudio users, eventually use "pulse"# For Jack/Jack2 users, use "jackplug"# For ALSA users, you may use "default" for your primary card# or you may use hw:# where # is the number of the card desiredif [[ -z "$MIXER" ]] ; thenMIXER="default"if command -v pulseaudio >/dev/null 2>&1 && pulseaudio --check ; then# pulseaudio is running, but not all installations use "pulse"if amixer -D pulse info >/dev/null 2>&1 ; thenMIXER="pulse"fifi[ -n "$(lsmod | grep jack)" ] && MIXER="jackplug"MIXER="${2:-$MIXER}"fi# The instance option sets the control to report and configure# This defaults to the first control of your selected mixer# For a list of the available, use `amixer -D $Your_Mixer scontrols`if [[ -z "$SCONTROL" ]] ; thenSCONTROL="${BLOCK_INSTANCE:-$(amixer -D $MIXER scontrols |sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" |head -n1)}"fi# The first parameter sets the step to change the volume by (and units to display)# This may be in in % or dB (eg. 5% or 3dB)if [[ -z "$STEP" ]] ; thenSTEP="${1:-5%}"fi# AMIXER(1):# "Use the mapped volume for evaluating the percentage representation like alsamixer, to be# more natural for human ear."NATURAL_MAPPING=${NATURAL_MAPPING:-0}if [[ "$NATURAL_MAPPING" != "0" ]] ; thenAMIXER_PARAMS="-M"fi#------------------------------------------------------------------------capability() { # Return "Capture" if the device is a capture deviceamixer $AMIXER_PARAMS -D $MIXER get $SCONTROL |sed -n "s/ Capabilities:.*cvolume.*/Capture/p"}volume() {amixer $AMIXER_PARAMS -D $MIXER get $SCONTROL $(capability)}format() {perl_filter='if (/.*\[(\d+%)\] (\[(-?\d+.\d+dB)\] )?\[(on|off)\]/)'perl_filter+='{CORE::say $4 eq "off" ? "x" : "'# If dB was selected, print that insteadperl_filter+=$([[ $STEP = *dB ]] && echo '$3' || echo '$1')perl_filter+='"; exit}'output=$(perl -ne "$perl_filter")echo "$LABEL$output"}#------------------------------------------------------------------------case $BLOCK_BUTTON in3) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) toggle ;; # right click, mute/unmute4) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) ${STEP}+ unmute ;; # scroll up, increase5) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) ${STEP}- unmute ;; # scroll down, decreaseesacvolume | format
#!/usr/bin/env bash# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------# The second parameter overrides the mixer selection# For PulseAudio users, eventually use "pulse"# For Jack/Jack2 users, use "jackplug"# For ALSA users, you may use "default" for your primary card# or you may use hw:# where # is the number of the card desiredif [[ -z "$MIXER" ]] ; thenMIXER="default"if command -v pulseaudio >/dev/null 2>&1 && pulseaudio --check ; then# pulseaudio is running, but not all installations use "pulse"if amixer -D pulse info >/dev/null 2>&1 ; thenMIXER="pulse"fifi[ -n "$(lsmod | grep jack)" ] && MIXER="jackplug"MIXER="${2:-$MIXER}"fi# The instance option sets the control to report and configure# This defaults to the first control of your selected mixer# For a list of the available, use `amixer -D $Your_Mixer scontrols`if [[ -z "$SCONTROL" ]] ; thenSCONTROL="${BLOCK_INSTANCE:-$(amixer -D $MIXER scontrols |sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" |head -n1)}"fi# The first parameter sets the step to change the volume by (and units to display)# This may be in in % or dB (eg. 5% or 3dB)if [[ -z "$STEP" ]] ; thenSTEP="${1:-5%}"fi# AMIXER(1):# "Use the mapped volume for evaluating the percentage representation like alsamixer, to be# more natural for human ear."NATURAL_MAPPING=${NATURAL_MAPPING:-0}if [[ "$NATURAL_MAPPING" != "0" ]] ; thenAMIXER_PARAMS="-M"fi#------------------------------------------------------------------------capability() { # Return "Capture" if the device is a capture deviceamixer $AMIXER_PARAMS -D $MIXER get $SCONTROL |sed -n "s/ Capabilities:.*cvolume.*/Capture/p"}volume() {amixer $AMIXER_PARAMS -D $MIXER get $SCONTROL $(capability)}format() {perl_filter='if (/.*\[(\d+%)\] (\[(-?\d+.\d+dB)\] )?\[(on|off)\]/)'perl_filter+='{CORE::say $4 eq "off" ? "x" : "'# If dB was selected, print that insteadperl_filter+=$([[ $STEP = *dB ]] && echo '$3' || echo '$1')perl_filter+='"; exit}'output=$(perl -ne "$perl_filter")echo "$LABEL$output"}#------------------------------------------------------------------------case $BLOCK_BUTTON in3) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) toggle ;; # right click, mute/unmute4) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) ${STEP}+ unmute ;; # scroll up, increase5) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) ${STEP}- unmute ;; # scroll down, decreaseesacvolume | format
#!/usr/bin/env python3## Copyright (C) 2015 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to output connected usb storage device info.import osdef _default(name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)################################################################################ BEGIN CONFIG# Most of these can be specified as command line options, run with --help for# more information.# You may edit any of the following entries. DO NOT delete any of them, else# the main script will have unpredictable behavior.################################################################################ Color options, can be a color name or #RRGGBBINFO_TEXT_COLOR = _default("INFO_TEXT_COLOR", "white")MOUNTED_COLOR = _default("MOUNTED_COLOR", "green")PLUGGED_COLOR = _default("PLUGGED_COLOR", "gray")LOCKED_COLOR = _default("LOCKED_COLOR", "gray")UNLOCKED_NOT_MOUNTED_COLOR = _default("UNLOCKED_NOT_MOUNTED_COLOR", "yellow")PARTITIONLESS_COLOR = _default("PARTITIONLESS_COLOR", "red")# Default textsPARTITIONLESS_TEXT = _default("PARTITIONLESS_TEXT", "no partitions")SEPARATOR = _default("SEPARATOR", "<span color='gray'> | </span>")# Indicate whether an encrypted partition is locked/unlocked, "" is allowed.LOCKED_INDICATOR = _default("LOCKED_INDICATOR", "\uf023 ")UNLOCKED_INDICATOR = _default("UNLOCKED_INDICATOR", "\uf09c ")# Shows instead of space available when a partition is mounted readonlyREADONLY_INDICATOR = _default("READONLY_INDICATOR", "ro")# Maximum length of a filesystem label to display. Use None to disable# truncation, a positive integer to right truncate to that many characters, or# a negative integer to left truncate to that many characters. Setting this# option to 0 will disable the displaying of filesystem labels.TRUNCATE_FS_LABELS = _default("TRUNCASE_FS_LABELS", None)# List of devices to ignore. Must be a valid python3 representation of a list# of stringsIGNORE_LIST = _default("IGNORE_LIST", "[]")if IGNORE_LIST:import astIGNORE_LIST = list(map(lambda p:p if p.startswith("/")else "/dev/{}".format(p),ast.literal_eval(IGNORE_LIST)))# Edit this function to ignore certain devices (e.g. those that are always# plugged in).# The dictionary udev_attributes_dict contains all the attributes given by# udevadm info --query=propery --name=$pathdef ignore(path, udev_attributes_dict):# E.g. how to ignore devices whose device name begins with /dev/sda# if udev_attributes_dict["DEVNAME"].startswith("/dev/sda"):# return Truereturn False# Edit this function to ignore devices before the udev attributes are# computed in order to save time and memory.def fastIgnore(path):if path in IGNORE_LIST:return True# E.g. how to to ignore devices whose path begins with /dev/sda# if path.startswith("/dev/sda"):# return True# E.g. how to ignore a fixed set of paths# if path in [ "/dev/path1", "/dev/path2", "/dev/path3" ]:# return Truereturn False################################################################################ END CONFIG# DO NOT EDIT ANYTHING AFTER THIS POINT UNLESS YOU KNOW WHAT YOU ARE DOING###############################################################################from subprocess import check_outputimport argparsedef pangoEscape(text):return text.replace("&", "&").replace("<", "<").replace(">", ">")def getLeafDevicePaths():lines = check_output(['lsblk', '-lpno', 'NAME'], universal_newlines=True)lines = lines.split("\n")lines = filter(lambda s: s[:4]=='/dev', lines)lines = map(lambda s: s.split(' ')[0], lines)lines = filter(None, lines)return linesdef getKernelName(path):return check_output(['lsblk', '-lndo', 'KNAME', path],universal_newlines=True).rstrip("\n")def getDeviceType(path):return check_output(['lsblk', '-no', 'TYPE', path],universal_newlines=True).strip()def getFSType(path):global attributeMapsreturn attributeMaps[path].get("ID_FS_TYPE")def isLUKSPartition(path):return getFSType(path) == "crypto_LUKS"def isSwapPartition(path):return getFSType(path) == "swap"def getFSLabel(path):global attributeMapslabel = attributeMaps[path].get("ID_FS_LABEL_ENC", "")if label:label = label.encode().decode("unicode-escape")if type(TRUNCATE_FS_LABELS) == int:if TRUNCATE_FS_LABELS >= 0:label = label[:TRUNCATE_FS_LABELS]elif TRUNCATE_FS_LABELS < 0:label = label[TRUNCATE_FS_LABELS:]return labeldef getFSOptions(path):lines = check_output(['findmnt', '-no', 'FS-OPTIONS', path],universal_newlines=True).strip()lines = lines.split(",")return linesdef isReadOnly(path):return "ro" in getFSOptions(path)def isExtendedPartitionMarker(path):global attributeMapsMARKERS = ["0xf", "0x5"]return attributeMaps[path].get("ID_PART_ENTRY_TYPE") in MARKERSdef getMountPoint(path):return check_output(['lsblk', '-ndo', 'MOUNTPOINT', path],universal_newlines=True).rstrip("\n")def getSpaceAvailable(path):lines = check_output(['df', '-h', '--output=avail', path],universal_newlines=True)lines = lines.split("\n")if len(lines) != 3:return ""else:return lines[1].strip()def getLockedCryptOutput(path):form = "<span color='{}'>[{}{}]</span>"kname = pangoEscape(getKernelName(path))output = form.format(LOCKED_COLOR, LOCKED_INDICATOR, kname)return outputdef getParentKernelName(path):lines = check_output(['lsblk', '-nso', 'KNAME', path],universal_newlines=True)lines = lines.split("\n")if len(lines) > 2:return lines[1].rstrip("\n")else:return ""def getUnlockedCryptOutput(path):mountPoint = getMountPoint(path)if mountPoint:color = MOUNTED_COLORif isReadOnly(path):spaceAvail = READONLY_INDICATORelse:spaceAvail = pangoEscape(getSpaceAvailable(path))mountPoint = "<i>{}</i>:".format(pangoEscape(mountPoint))else:color = UNLOCKED_NOT_MOUNTED_COLORspaceAvail = ""kernelName = pangoEscape(getKernelName(path))parentKernelName = pangoEscape(getParentKernelName(path))block = "<span color='{}'>[{}{}:{}]</span>"block = block.format(color, UNLOCKED_INDICATOR,parentKernelName, kernelName)label = pangoEscape(getFSLabel(path))if label:label = '"{}"'.format(label)items = [block, label, mountPoint, spaceAvail]return " ".join(filter(None, items))def getSwapOutput(path):return ""def getUnencryptedPartitionOutput(path):mountPoint = getMountPoint(path)if mountPoint:color = MOUNTED_COLORif isReadOnly(path):spaceAvail = READONLY_INDICATORelse:spaceAvail = pangoEscape(getSpaceAvailable(path))mountPoint = "<i>{}</i>:".format(pangoEscape(mountPoint))else:color = PLUGGED_COLORspaceAvail = ""kernelName = pangoEscape(getKernelName(path))block = "<span color='{}'>[{}]</span>"block = block.format(color, kernelName)label = pangoEscape(getFSLabel(path))if label:label = '"{}"'.format(label)items = [block, label, mountPoint, spaceAvail]return " ".join(filter(None, items))def getDiskWithNoPartitionsOutput(path):form = "<span color='{}'>[{}] {}</span>"kernelName = pangoEscape(getKernelName(path))return form.format(PARTITIONLESS_COLOR, kernelName, PARTITIONLESS_TEXT)def getOutput(path):if isSwapPartition(path):return getSwapOutput(path)t = getDeviceType(path)if t == "part":if isExtendedPartitionMarker(path):return ""elif isLUKSPartition(path):return getLockedCryptOutput(path)else:return getUnencryptedPartitionOutput(path)elif t == "disk":return getDiskWithNoPartitionsOutput(path)elif t == "crypt":return getUnlockedCryptOutput(path)elif t == "rom":return ""def makeAttributeMap(path):attributeMap = {}lines = check_output(['udevadm', 'info', '--query=property', '--name={}'.format(path)],universal_newlines=True)lines = lines.split("\n")for line in lines:if line:key, val = line.split("=", maxsplit=1)attributeMap[key] = valreturn attributeMapdef getAttributeMaps(paths):return {path: makeAttributeMap(path) for path in paths}def parseArguments():dsc = " ".join(["i3blocks blocklet script","to output connected usb storage device info"])parser = argparse.ArgumentParser(prog="usb.py", description=dsc)def unArg(flag, text, default, *args, **kwargs):parser.add_argument(flag, nargs=1,help="{}. Default: {}".format(text, default), *args, **kwargs)def unArgs(flagTempl, textTempl, vals):for flag, text, default in vals:unArg(flagTempl.format(flag), textTempl.format(text), default)unArgs("--{}-color", "Set the color of {}",[("info-text", "info text", INFO_TEXT_COLOR),("mounted", "mounted devices", MOUNTED_COLOR),("plugged", "plugged devices", PLUGGED_COLOR),("locked", "locked crypt devices", LOCKED_COLOR),("unlocked-not-mounted", "unlocked not mounted crypt devices",UNLOCKED_NOT_MOUNTED_COLOR),("partitionless", "devices with no partitions",PARTITIONLESS_COLOR)])unArg("--partitionless-text","Set the text to display for a device with no partitions",PARTITIONLESS_TEXT)unArg("--separator", "Set the separator between devices", SEPARATOR)unArgs("--{}-indicator", "Set the indicator to use for {}",[("locked", "a locked crypt device", LOCKED_INDICATOR),("unlocked", "an unlocked crypt device", UNLOCKED_INDICATOR),("readonly", "a readonly device", READONLY_INDICATOR)])unArg("--truncate-fs-labels","(integer) Trucate device labels to a certain number of characters",TRUNCATE_FS_LABELS, type=int)ignoreText = " ".join(["Ignore a device by path.","If path doesn't begin with / then it is assumed to be in /dev/"])parser.add_argument("-i", "--ignore", action="append", help=ignoreText)args = parser.parse_args()setParsedArgs(args)def setParsedArgs(args):if args.info_text_color is not None:global INFO_TEXT_COLORINFO_TEXT_COLOR = args.info_text_color[0]if args.mounted_color is not None:global MOUNTED_COLORMOUNTED_COLOR = args.mounted_color[0]if args.plugged_color is not None:global PLUGGED_COLORPLUGGED_COLOR = args.plugged_color[0]if args.locked_color is not None:global LOCKED_COLORLOCKED_COLOR = args.locked_color[0]if args.unlocked_not_mounted_color is not None:global UNLOCKED_NOT_MOUNTED_COLORUNLOCKED_NOT_MOUNTED_COLOR = args.unlocked_not_mounted_color[0]if args.partitionless_color is not None:global PARTITIONLESS_COLORPARTITIONLESS_COLOR = args.partitionless_color[0]if args.partitionless_text is not None:global PARTITIONLESS_TEXTPARTITIONLESS_TEXT = args.partitionless_text[0]if args.separator is not None:global SEPARATORSEPARATOR = args.separator[0]if args.locked_indicator is not None:global LOCKED_INDICATORLOCKED_INDICATOR = args.locked_indicator[0]if args.unlocked_indicator is not None:global UNLOCKED_INDICATORUNLOCKED_INDICATOR = args.unlocked_indicator[0]if args.readonly_indicator is not None:global READONLY_INDICATORREADONLY_INDICATOR = args.readonly_indicator[0]if args.truncate_fs_labels is not None:global TRUNCATE_FS_LABELSTRUNCATE_FS_LABELS = args.truncate_fs_labels[0]if args.ignore is not None:args.ignore = list(map(lambda p:p if p.startswith("/") else "/dev/{}".format(p),args.ignore))global fastIgnoreoldFastIgnore = fastIgnoredef newFastIgnore(path):return oldFastIgnore(path) or path in args.ignorefastIgnore = newFastIgnoreparseArguments()leaves = getLeafDevicePaths()leaves = [path for path in leaves if not fastIgnore(path)]attributeMaps = getAttributeMaps(leaves)leaves = (path for path in leaves if not ignore(path, attributeMaps[path]))outputs = filter(None, map(getOutput, leaves))output = SEPARATOR.join(outputs)if output:output = "<span color='{}'>{}</span>".format(INFO_TEXT_COLOR, output)print(output)print(output)
#!/usr/bin/env python3## Copyright (C) 2015 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to output connected usb storage device info.import osdef _default(name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)################################################################################ BEGIN CONFIG# Most of these can be specified as command line options, run with --help for# more information.# You may edit any of the following entries. DO NOT delete any of them, else# the main script will have unpredictable behavior.################################################################################ Color options, can be a color name or #RRGGBBINFO_TEXT_COLOR = _default("INFO_TEXT_COLOR", "white")MOUNTED_COLOR = _default("MOUNTED_COLOR", "green")PLUGGED_COLOR = _default("PLUGGED_COLOR", "gray")LOCKED_COLOR = _default("LOCKED_COLOR", "gray")UNLOCKED_NOT_MOUNTED_COLOR = _default("UNLOCKED_NOT_MOUNTED_COLOR", "yellow")PARTITIONLESS_COLOR = _default("PARTITIONLESS_COLOR", "red")# Default textsPARTITIONLESS_TEXT = _default("PARTITIONLESS_TEXT", "no partitions")SEPARATOR = _default("SEPARATOR", "<span color='gray'> | </span>")# Indicate whether an encrypted partition is locked/unlocked, "" is allowed.LOCKED_INDICATOR = _default("LOCKED_INDICATOR", "\uf023 ")UNLOCKED_INDICATOR = _default("UNLOCKED_INDICATOR", "\uf09c ")# Shows instead of space available when a partition is mounted readonlyREADONLY_INDICATOR = _default("READONLY_INDICATOR", "ro")# Maximum length of a filesystem label to display. Use None to disable# truncation, a positive integer to right truncate to that many characters, or# a negative integer to left truncate to that many characters. Setting this# option to 0 will disable the displaying of filesystem labels.TRUNCATE_FS_LABELS = _default("TRUNCASE_FS_LABELS", None)# List of devices to ignore. Must be a valid python3 representation of a list# of stringsIGNORE_LIST = _default("IGNORE_LIST", "[]")if IGNORE_LIST:import astIGNORE_LIST = list(map(lambda p:p if p.startswith("/")else "/dev/{}".format(p),ast.literal_eval(IGNORE_LIST)))# Edit this function to ignore certain devices (e.g. those that are always# plugged in).# The dictionary udev_attributes_dict contains all the attributes given by# udevadm info --query=propery --name=$pathdef ignore(path, udev_attributes_dict):# E.g. how to ignore devices whose device name begins with /dev/sda# if udev_attributes_dict["DEVNAME"].startswith("/dev/sda"):# return Truereturn False# Edit this function to ignore devices before the udev attributes are# computed in order to save time and memory.def fastIgnore(path):if path in IGNORE_LIST:return True# E.g. how to to ignore devices whose path begins with /dev/sda# if path.startswith("/dev/sda"):# return True# E.g. how to ignore a fixed set of paths# if path in [ "/dev/path1", "/dev/path2", "/dev/path3" ]:# return Truereturn False################################################################################ END CONFIG# DO NOT EDIT ANYTHING AFTER THIS POINT UNLESS YOU KNOW WHAT YOU ARE DOING###############################################################################from subprocess import check_outputimport argparsedef pangoEscape(text):return text.replace("&", "&").replace("<", "<").replace(">", ">")def getLeafDevicePaths():lines = check_output(['lsblk', '-lpno', 'NAME'], universal_newlines=True)lines = lines.split("\n")lines = filter(lambda s: s[:4]=='/dev', lines)lines = map(lambda s: s.split(' ')[0], lines)lines = filter(None, lines)return linesdef getKernelName(path):return check_output(['lsblk', '-lndo', 'KNAME', path],universal_newlines=True).rstrip("\n")def getDeviceType(path):return check_output(['lsblk', '-no', 'TYPE', path],universal_newlines=True).strip()def getFSType(path):global attributeMapsreturn attributeMaps[path].get("ID_FS_TYPE")def isLUKSPartition(path):return getFSType(path) == "crypto_LUKS"def isSwapPartition(path):return getFSType(path) == "swap"def getFSLabel(path):global attributeMapslabel = attributeMaps[path].get("ID_FS_LABEL_ENC", "")if label:label = label.encode().decode("unicode-escape")if type(TRUNCATE_FS_LABELS) == int:if TRUNCATE_FS_LABELS >= 0:label = label[:TRUNCATE_FS_LABELS]elif TRUNCATE_FS_LABELS < 0:label = label[TRUNCATE_FS_LABELS:]return labeldef getFSOptions(path):lines = check_output(['findmnt', '-no', 'FS-OPTIONS', path],universal_newlines=True).strip()lines = lines.split(",")return linesdef isReadOnly(path):return "ro" in getFSOptions(path)def isExtendedPartitionMarker(path):global attributeMapsMARKERS = ["0xf", "0x5"]return attributeMaps[path].get("ID_PART_ENTRY_TYPE") in MARKERSdef getMountPoint(path):return check_output(['lsblk', '-ndo', 'MOUNTPOINT', path],universal_newlines=True).rstrip("\n")def getSpaceAvailable(path):lines = check_output(['df', '-h', '--output=avail', path],universal_newlines=True)lines = lines.split("\n")if len(lines) != 3:return ""else:return lines[1].strip()def getLockedCryptOutput(path):form = "<span color='{}'>[{}{}]</span>"kname = pangoEscape(getKernelName(path))output = form.format(LOCKED_COLOR, LOCKED_INDICATOR, kname)return outputdef getParentKernelName(path):lines = check_output(['lsblk', '-nso', 'KNAME', path],universal_newlines=True)lines = lines.split("\n")if len(lines) > 2:return lines[1].rstrip("\n")else:return ""def getUnlockedCryptOutput(path):mountPoint = getMountPoint(path)if mountPoint:color = MOUNTED_COLORif isReadOnly(path):spaceAvail = READONLY_INDICATORelse:spaceAvail = pangoEscape(getSpaceAvailable(path))mountPoint = "<i>{}</i>:".format(pangoEscape(mountPoint))else:color = UNLOCKED_NOT_MOUNTED_COLORspaceAvail = ""kernelName = pangoEscape(getKernelName(path))parentKernelName = pangoEscape(getParentKernelName(path))block = "<span color='{}'>[{}{}:{}]</span>"block = block.format(color, UNLOCKED_INDICATOR,parentKernelName, kernelName)label = pangoEscape(getFSLabel(path))if label:label = '"{}"'.format(label)items = [block, label, mountPoint, spaceAvail]return " ".join(filter(None, items))def getSwapOutput(path):return ""def getUnencryptedPartitionOutput(path):mountPoint = getMountPoint(path)if mountPoint:color = MOUNTED_COLORif isReadOnly(path):spaceAvail = READONLY_INDICATORelse:spaceAvail = pangoEscape(getSpaceAvailable(path))mountPoint = "<i>{}</i>:".format(pangoEscape(mountPoint))else:color = PLUGGED_COLORspaceAvail = ""kernelName = pangoEscape(getKernelName(path))block = "<span color='{}'>[{}]</span>"block = block.format(color, kernelName)label = pangoEscape(getFSLabel(path))if label:label = '"{}"'.format(label)items = [block, label, mountPoint, spaceAvail]return " ".join(filter(None, items))def getDiskWithNoPartitionsOutput(path):form = "<span color='{}'>[{}] {}</span>"kernelName = pangoEscape(getKernelName(path))return form.format(PARTITIONLESS_COLOR, kernelName, PARTITIONLESS_TEXT)def getOutput(path):if isSwapPartition(path):return getSwapOutput(path)t = getDeviceType(path)if t == "part":if isExtendedPartitionMarker(path):return ""elif isLUKSPartition(path):return getLockedCryptOutput(path)else:return getUnencryptedPartitionOutput(path)elif t == "disk":return getDiskWithNoPartitionsOutput(path)elif t == "crypt":return getUnlockedCryptOutput(path)elif t == "rom":return ""def makeAttributeMap(path):attributeMap = {}lines = check_output(['udevadm', 'info', '--query=property', '--name={}'.format(path)],universal_newlines=True)lines = lines.split("\n")for line in lines:if line:key, val = line.split("=", maxsplit=1)attributeMap[key] = valreturn attributeMapdef getAttributeMaps(paths):return {path: makeAttributeMap(path) for path in paths}def parseArguments():dsc = " ".join(["i3blocks blocklet script","to output connected usb storage device info"])parser = argparse.ArgumentParser(prog="usb.py", description=dsc)def unArg(flag, text, default, *args, **kwargs):parser.add_argument(flag, nargs=1,help="{}. Default: {}".format(text, default), *args, **kwargs)def unArgs(flagTempl, textTempl, vals):for flag, text, default in vals:unArg(flagTempl.format(flag), textTempl.format(text), default)unArgs("--{}-color", "Set the color of {}",[("info-text", "info text", INFO_TEXT_COLOR),("mounted", "mounted devices", MOUNTED_COLOR),("plugged", "plugged devices", PLUGGED_COLOR),("locked", "locked crypt devices", LOCKED_COLOR),("unlocked-not-mounted", "unlocked not mounted crypt devices",UNLOCKED_NOT_MOUNTED_COLOR),("partitionless", "devices with no partitions",PARTITIONLESS_COLOR)])unArg("--partitionless-text","Set the text to display for a device with no partitions",PARTITIONLESS_TEXT)unArg("--separator", "Set the separator between devices", SEPARATOR)unArgs("--{}-indicator", "Set the indicator to use for {}",[("locked", "a locked crypt device", LOCKED_INDICATOR),("unlocked", "an unlocked crypt device", UNLOCKED_INDICATOR),("readonly", "a readonly device", READONLY_INDICATOR)])unArg("--truncate-fs-labels","(integer) Trucate device labels to a certain number of characters",TRUNCATE_FS_LABELS, type=int)ignoreText = " ".join(["Ignore a device by path.","If path doesn't begin with / then it is assumed to be in /dev/"])parser.add_argument("-i", "--ignore", action="append", help=ignoreText)args = parser.parse_args()setParsedArgs(args)def setParsedArgs(args):if args.info_text_color is not None:global INFO_TEXT_COLORINFO_TEXT_COLOR = args.info_text_color[0]if args.mounted_color is not None:global MOUNTED_COLORMOUNTED_COLOR = args.mounted_color[0]if args.plugged_color is not None:global PLUGGED_COLORPLUGGED_COLOR = args.plugged_color[0]if args.locked_color is not None:global LOCKED_COLORLOCKED_COLOR = args.locked_color[0]if args.unlocked_not_mounted_color is not None:global UNLOCKED_NOT_MOUNTED_COLORUNLOCKED_NOT_MOUNTED_COLOR = args.unlocked_not_mounted_color[0]if args.partitionless_color is not None:global PARTITIONLESS_COLORPARTITIONLESS_COLOR = args.partitionless_color[0]if args.partitionless_text is not None:global PARTITIONLESS_TEXTPARTITIONLESS_TEXT = args.partitionless_text[0]if args.separator is not None:global SEPARATORSEPARATOR = args.separator[0]if args.locked_indicator is not None:global LOCKED_INDICATORLOCKED_INDICATOR = args.locked_indicator[0]if args.unlocked_indicator is not None:global UNLOCKED_INDICATORUNLOCKED_INDICATOR = args.unlocked_indicator[0]if args.readonly_indicator is not None:global READONLY_INDICATORREADONLY_INDICATOR = args.readonly_indicator[0]if args.truncate_fs_labels is not None:global TRUNCATE_FS_LABELSTRUNCATE_FS_LABELS = args.truncate_fs_labels[0]if args.ignore is not None:args.ignore = list(map(lambda p:p if p.startswith("/") else "/dev/{}".format(p),args.ignore))global fastIgnoreoldFastIgnore = fastIgnoredef newFastIgnore(path):return oldFastIgnore(path) or path in args.ignorefastIgnore = newFastIgnoreparseArguments()leaves = getLeafDevicePaths()leaves = [path for path in leaves if not fastIgnore(path)]attributeMaps = getAttributeMaps(leaves)leaves = (path for path in leaves if not ignore(path, attributeMaps[path]))outputs = filter(None, map(getOutput, leaves))output = SEPARATOR.join(outputs)if output:output = "<span color='{}'>{}</span>".format(INFO_TEXT_COLOR, output)print(output)print(output)
#!/bin/bashif [[ -z ${COMMAND_ON} || -z ${COMMAND_OFF} || -z ${COMMAND_STATUS} ]]; thenecho "All of COMMAND_ON, COMMAND_OFF, and COMMAND_STATUS are required" >&2exit 1fion_cmd=${COMMAND_ON}off_cmd=${COMMAND_OFF}status_cmd=${COMMAND_STATUS}if (( ${BLOCK_BUTTON:-0} == 1 )); theneval $status_cmd 2>&1 >/dev/nullif (( $? == 0 )); theneval $off_cmd 2>&1 >/dev/nullelseeval $on_cmd 2>&1 >/dev/nullfifieval $status_cmd 2>&1 >/dev/nullif (( $? == 0 )); thenCOLOR=${COLOR_ON}elseCOLOR=${COLOR_OFF:-#555555}fiechoechoecho $COLOR
#!/bin/bashif [[ -z ${COMMAND_ON} || -z ${COMMAND_OFF} || -z ${COMMAND_STATUS} ]]; thenecho "All of COMMAND_ON, COMMAND_OFF, and COMMAND_STATUS are required" >&2exit 1fion_cmd=${COMMAND_ON}off_cmd=${COMMAND_OFF}status_cmd=${COMMAND_STATUS}if (( ${BLOCK_BUTTON:-0} == 1 )); theneval $status_cmd 2>&1 >/dev/nullif (( $? == 0 )); theneval $off_cmd 2>&1 >/dev/nullelseeval $on_cmd 2>&1 >/dev/nullfifieval $status_cmd 2>&1 >/dev/nullif (( $? == 0 )); thenCOLOR=${COLOR_ON}elseCOLOR=${COLOR_OFF:-#555555}fiechoechoecho $COLOR
#! /usr/bin/env bash###### Default environment variables ######STOPWATCH_LABEL=${STOPWATCH_LABEL:-stopwatch}TIMER_LABEL=${TIMER_LABEL:-timer}DEFAULT_MODE=${DEFAULT_MODE:-timer}DEFAULT_STOPWATCH=${DEFAULT_STOPWATCH:-0}DEFAULT_TIMER=${DEFAULT_TIMER:-60}PLAY_LABEL=${PLAY_LABEL:-(playing)}PAUSE_LABEL=${PAUSE_LABEL:-(paused)}TIMER_LOOP=${TIMER_LOOP:-false}NEUTRAL_COLOR=${NEUTRAL_COLOR:-#000000}###### Default environment variables ############ Functions ######error() {echo Error: "$@" 1>&2}next_mode() {mode=$(( (mode + 1) % ${#modes[@]} ))set_mode}play_pause() {$running && pause || play}play() {running=truestatus_symbol=$PLAY_LABEL}pause() {running=falsestatus_symbol=$PAUSE_LABEL}reset_times() {unset timeset_mode}set_mode() {case ${modes[$mode]} in'timer' )running=falsestatus_symbol=$PAUSE_LABELinitial_time=${initial_time-$DEFAULT_TIMER}time=$initial_timeincr=-1;;'stopwatch' )running=falsestatus_symbol=$PAUSE_LABELtime=${time-$DEFAULT_STOPWATCH}fgcolor='#FFFFFF'bgcolor=$NEUTRAL_COLORincr=1;;esac}compute_color() {t=$1hue360=$(( 120*t/initial_time ))tmp=$(( hue360 % 120 - 60 ))tmp=$(( (60 - ${tmp#-})*255/60 ))if (( hue360 < 60 && hue360 >= 0 )); thenR=255 G=$tmp B=0elif (( hue360 <= 120 && hue360 >= 60 )); thenR=$tmp G=255 B=0fiprintf '#%06X\n' $(( R*16*16*16*16 + G*16*16 + B ))}prettify_time() {seconds=$timeif (( time >= 60 )); thenminutes=$(( time / 60 ))seconds=$(( time % 60 ))(( seconds < 10 )) && seconds=0$secondsfiif (( minutes >= 60 )); thenhours=$(( minutes / 60 ))minutes=$(( minutes % 60 ))(( minutes < 10 )) && minutes=0$minutesfiecho $hours${hours+:}$minutes${minutes+:}$seconds}###### Functions ############ Internal variables ######modes=([0]='timer' [1]='stopwatch')labels=([0]="$TIMER_LABEL" [1]="$STOPWATCH_LABEL")###### Internal variables ############ First run initialization ######if [[ ! -v time ]]; thenfor i in "${!modes[@]}"; doif [[ "${modes[$i]}" == "$DEFAULT_MODE" ]]; thenmode=$ifidoneset_modefi###### First run initialization ############ Click processing ######case $BLOCK_BUTTON in1 )play_pause;;2 )reset_times;;3 )next_modereset_timespause;;4 )$running && pauseinitial_time=$(( initial_time + 1 ))time=$initial_time;;5 )$running && pauseinitial_time=$(( initial_time - 1 ))time=$initial_time;;esac###### Click processing ############ Time increment ######$running && time=$(( time + incr ))if (( mode == 0 )); thenif (( time <= 0 )); thenbgcolor='#FF0000'fgcolor=$NEUTRAL_COLORtime=0pauseelif (( time > 0 )); thenfgcolor=$(compute_color $time)bgcolor=$NEUTRAL_COLORfielsebgcolor=$NEUTRAL_COLORfgcolor='#FFFFFF'fifull_text="${labels[$mode]} $status_symbol $(prettify_time)"if (( mode == 0 && time == 0 )); then$TIMER_LOOP && reset_times && playfi###### Time increment ############ Output ######cat << EOF{"full_text":"$full_text",\"status_symbol":"$status_symbol",\"time":"$time",\"initial_time":"$initial_time",\"incr":"$incr",\"running":"$running",\"mode":"$mode",\"color":"$fgcolor",\"background":"$bgcolor"}EOF###### Output ######
#! /usr/bin/env bash###### Default environment variables ######STOPWATCH_LABEL=${STOPWATCH_LABEL:-stopwatch}TIMER_LABEL=${TIMER_LABEL:-timer}DEFAULT_MODE=${DEFAULT_MODE:-timer}DEFAULT_STOPWATCH=${DEFAULT_STOPWATCH:-0}DEFAULT_TIMER=${DEFAULT_TIMER:-60}PLAY_LABEL=${PLAY_LABEL:-(playing)}PAUSE_LABEL=${PAUSE_LABEL:-(paused)}TIMER_LOOP=${TIMER_LOOP:-false}NEUTRAL_COLOR=${NEUTRAL_COLOR:-#000000}###### Default environment variables ############ Functions ######error() {echo Error: "$@" 1>&2}next_mode() {mode=$(( (mode + 1) % ${#modes[@]} ))set_mode}play_pause() {$running && pause || play}play() {running=truestatus_symbol=$PLAY_LABEL}pause() {running=falsestatus_symbol=$PAUSE_LABEL}reset_times() {unset timeset_mode}set_mode() {case ${modes[$mode]} in'timer' )running=falsestatus_symbol=$PAUSE_LABELinitial_time=${initial_time-$DEFAULT_TIMER}time=$initial_timeincr=-1;;'stopwatch' )running=falsestatus_symbol=$PAUSE_LABELtime=${time-$DEFAULT_STOPWATCH}fgcolor='#FFFFFF'bgcolor=$NEUTRAL_COLORincr=1;;esac}compute_color() {t=$1hue360=$(( 120*t/initial_time ))tmp=$(( hue360 % 120 - 60 ))tmp=$(( (60 - ${tmp#-})*255/60 ))if (( hue360 < 60 && hue360 >= 0 )); thenR=255 G=$tmp B=0elif (( hue360 <= 120 && hue360 >= 60 )); thenR=$tmp G=255 B=0fiprintf '#%06X\n' $(( R*16*16*16*16 + G*16*16 + B ))}prettify_time() {seconds=$timeif (( time >= 60 )); thenminutes=$(( time / 60 ))seconds=$(( time % 60 ))(( seconds < 10 )) && seconds=0$secondsfiif (( minutes >= 60 )); thenhours=$(( minutes / 60 ))minutes=$(( minutes % 60 ))(( minutes < 10 )) && minutes=0$minutesfiecho $hours${hours+:}$minutes${minutes+:}$seconds}###### Functions ############ Internal variables ######modes=([0]='timer' [1]='stopwatch')labels=([0]="$TIMER_LABEL" [1]="$STOPWATCH_LABEL")###### Internal variables ############ First run initialization ######if [[ ! -v time ]]; thenfor i in "${!modes[@]}"; doif [[ "${modes[$i]}" == "$DEFAULT_MODE" ]]; thenmode=$ifidoneset_modefi###### First run initialization ############ Click processing ######case $BLOCK_BUTTON in1 )play_pause;;2 )reset_times;;3 )next_modereset_timespause;;4 )$running && pauseinitial_time=$(( initial_time + 1 ))time=$initial_time;;5 )$running && pauseinitial_time=$(( initial_time - 1 ))time=$initial_time;;esac###### Click processing ############ Time increment ######$running && time=$(( time + incr ))if (( mode == 0 )); thenif (( time <= 0 )); thenbgcolor='#FF0000'fgcolor=$NEUTRAL_COLORtime=0pauseelif (( time > 0 )); thenfgcolor=$(compute_color $time)bgcolor=$NEUTRAL_COLORfielsebgcolor=$NEUTRAL_COLORfgcolor='#FFFFFF'fifull_text="${labels[$mode]} $status_symbol $(prettify_time)"if (( mode == 0 && time == 0 )); then$TIMER_LOOP && reset_times && playfi###### Time increment ############ Output ######cat << EOF{"full_text":"$full_text",\"status_symbol":"$status_symbol",\"time":"$time",\"initial_time":"$initial_time",\"incr":"$incr",\"running":"$running",\"mode":"$mode",\"color":"$fgcolor",\"background":"$bgcolor"}EOF###### Output ######
#!/usr/bin/env perluse strict;use warnings;use POSIX qw/strftime/;my $click = $ENV{BLOCK_BUTTON} || 0;my $format = $ENV{BLOCK_INSTANCE} || $ENV{STRFTIME_FORMAT} || "%H:%M";my $tz_file = shift || $ENV{TZ_FILE} || "$ENV{HOME}/.tz";$tz_file = glob($tz_file);my $default_tz = get_default_tz();my $tzones = $ENV{TZONES} || '$DEFAULT_TZ';$tzones =~ s/\$DEFAULT_TZ/$default_tz/g;my @tz_list = split(/,/, $tzones);my @tz_labels = split(/,/, $ENV{TZ_LABELS} || "");if (scalar(@tz_list) != scalar(@tz_labels)) {@tz_labels = @tz_list;}my $current_tz;if ($click == 1) {$current_tz = get_tz();my %tzmap;$tzmap{""} = $tz_list[0];my $prev = $tz_list[0];foreach my $tz (@tz_list) {$tzmap{$prev} = $tz;$prev = $tz;}$tzmap{$prev} = $tz_list[0];if (exists $tzmap{$current_tz}) {set_tz($tzmap{$current_tz});$current_tz = $tzmap{$current_tz};}}# How each timezone will be displayed in the bar.my %display_map;for (my $i=0; $i < scalar(@tz_list); $i++) {$display_map{$tz_list[$i]} = $tz_labels[$i];}if (!defined $current_tz) {$current_tz = get_tz();set_tz($current_tz);}$ENV{TZ} = $current_tz;my $tz_display = "";if (!exists $display_map{$ENV{TZ}}) {$ENV{TZ} = $tz_list[0];set_tz($tz_list[0]);}$tz_display = $display_map{$ENV{TZ}};binmode(STDOUT, ":utf8");my $time = strftime($format, localtime());if ($tz_display eq "") {print "$time\n";} else {print "$time ($tz_display)\n";}sub get_tz {my $current_tz;if (-f $tz_file) {open my $fh, '<', $tz_file || die "Couldn't open file: $tz_file";$current_tz = <$fh>;chomp $current_tz;close $fh;}return $current_tz || get_default_tz();}sub set_tz {my $tz = shift;open my $fh, '>', $tz_file || die "Couldn't open file: $tz_file";print $fh $tz;close $fh;}sub get_default_tz {my $tz = "Europe/London";if (-f "/etc/timezone") {open my $fh, '<', "/etc/timezone" || die "Couldn't open file: /etc/timezone";$tz = <$fh>;chomp $tz;close $fh;} elsif (-l "/etc/localtime") {$tz = readlink "/etc/localtime";$tz = (split /zoneinfo\//, $tz)[-1];}return $tz;}
#!/usr/bin/env perluse strict;use warnings;use POSIX qw/strftime/;my $click = $ENV{BLOCK_BUTTON} || 0;my $format = $ENV{BLOCK_INSTANCE} || $ENV{STRFTIME_FORMAT} || "%H:%M";my $tz_file = shift || $ENV{TZ_FILE} || "$ENV{HOME}/.tz";$tz_file = glob($tz_file);my $default_tz = get_default_tz();my $tzones = $ENV{TZONES} || '$DEFAULT_TZ';$tzones =~ s/\$DEFAULT_TZ/$default_tz/g;my @tz_list = split(/,/, $tzones);my @tz_labels = split(/,/, $ENV{TZ_LABELS} || "");if (scalar(@tz_list) != scalar(@tz_labels)) {@tz_labels = @tz_list;}my $current_tz;if ($click == 1) {$current_tz = get_tz();my %tzmap;$tzmap{""} = $tz_list[0];my $prev = $tz_list[0];foreach my $tz (@tz_list) {$tzmap{$prev} = $tz;$prev = $tz;}$tzmap{$prev} = $tz_list[0];if (exists $tzmap{$current_tz}) {set_tz($tzmap{$current_tz});$current_tz = $tzmap{$current_tz};}}# How each timezone will be displayed in the bar.my %display_map;for (my $i=0; $i < scalar(@tz_list); $i++) {$display_map{$tz_list[$i]} = $tz_labels[$i];}if (!defined $current_tz) {$current_tz = get_tz();set_tz($current_tz);}$ENV{TZ} = $current_tz;my $tz_display = "";if (!exists $display_map{$ENV{TZ}}) {$ENV{TZ} = $tz_list[0];set_tz($tz_list[0]);}$tz_display = $display_map{$ENV{TZ}};binmode(STDOUT, ":utf8");my $time = strftime($format, localtime());if ($tz_display eq "") {print "$time\n";} else {print "$time ($tz_display)\n";}sub get_tz {my $current_tz;if (-f $tz_file) {open my $fh, '<', $tz_file || die "Couldn't open file: $tz_file";$current_tz = <$fh>;chomp $current_tz;close $fh;}return $current_tz || get_default_tz();}sub set_tz {my $tz = shift;open my $fh, '>', $tz_file || die "Couldn't open file: $tz_file";print $fh $tz;close $fh;}sub get_default_tz {my $tz = "Europe/London";if (-f "/etc/timezone") {open my $fh, '<', "/etc/timezone" || die "Couldn't open file: /etc/timezone";$tz = <$fh>;chomp $tz;close $fh;} elsif (-l "/etc/localtime") {$tz = readlink "/etc/localtime";$tz = (split /zoneinfo\//, $tz)[-1];}return $tz;}
#!/usr/bin/env perl# Copyright 2014 Pierre Mavro <deimos@deimos.fr># Copyright 2014 Vivien Didelot <vivien@didelot.org># Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com># Copyright 2014 Benjamin Chretien <chretien at lirmm dot fr># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.use strict;use warnings;use utf8;use Getopt::Long;binmode(STDOUT, ":utf8");# default valuesmy $t_warn = $ENV{T_WARN} || 70;my $t_crit = $ENV{T_CRIT} || 90;my $chip = $ENV{SENSOR_CHIP} || "";my $temperature = -9999;sub help {print "Usage: temperature [-w <warning>] [-c <critical>] [--chip <chip>]\n";print "-w <percent>: warning threshold to become yellow\n";print "-c <percent>: critical threshold to become red\n";print "--chip <chip>: sensor chip\n";exit 0;}GetOptions("help|h" => \&help,"w=i" => \$t_warn,"c=i" => \$t_crit,"chip=s" => \$chip);# Get chip temperatureopen (SENSORS, "sensors -u $chip |") or die;while (<SENSORS>) {if (/^\s+temp1_input:\s+[\+]*([\-]*\d+\.\d)/) {$temperature = $1;last;}}close(SENSORS);$temperature eq -9999 and die 'Cannot find temperature';# Print short_text, full_textprint "$temperature°C\n" x2;# Print color, if neededif ($temperature >= $t_crit) {print "#FF0000\n";exit 33;} elsif ($temperature >= $t_warn) {print "#FFFC00\n";}exit 0;
#!/usr/bin/env perl# Copyright 2014 Pierre Mavro <deimos@deimos.fr># Copyright 2014 Vivien Didelot <vivien@didelot.org># Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com># Copyright 2014 Benjamin Chretien <chretien at lirmm dot fr># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.use strict;use warnings;use utf8;use Getopt::Long;binmode(STDOUT, ":utf8");# default valuesmy $t_warn = $ENV{T_WARN} || 70;my $t_crit = $ENV{T_CRIT} || 90;my $chip = $ENV{SENSOR_CHIP} || "";my $temperature = -9999;sub help {print "Usage: temperature [-w <warning>] [-c <critical>] [--chip <chip>]\n";print "-w <percent>: warning threshold to become yellow\n";print "-c <percent>: critical threshold to become red\n";print "--chip <chip>: sensor chip\n";exit 0;}GetOptions("help|h" => \&help,"w=i" => \$t_warn,"c=i" => \$t_crit,"chip=s" => \$chip);# Get chip temperatureopen (SENSORS, "sensors -u $chip |") or die;while (<SENSORS>) {if (/^\s+temp1_input:\s+[\+]*([\-]*\d+\.\d)/) {$temperature = $1;last;}}close(SENSORS);$temperature eq -9999 and die 'Cannot find temperature';# Print short_text, full_textprint "$temperature°C\n" x2;# Print color, if neededif ($temperature >= $t_crit) {print "#FF0000\n";exit 33;} elsif ($temperature >= $t_warn) {print "#FFFC00\n";}exit 0;
#!/usr/bin/env python3"""Extracts information from taskwarrior and timewarrior to display in i3block."""# This is taskw.py v0.3.1import subprocessimport jsonimport osimport re# config options codedef _default(name, default="", arg_type=str):"""Set a parameter based on OS variable.Fix the argument type and fall back on given default."""val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)def _strbool(s):"""Return True if argument is t,T,true,TRUE etc."""return s.lower() in ["t", "true", "1"]# I don't know who originally wrote these functions,# but many of the python blocklets in i3blocks-contrib use it.# arch-update added this code on 25 March 2018 and as far as I can tell# this was the earliest use.maxlen = _default("TASKW_MAX_LENGTH", default=35, arg_type=int)notask_msg = _default("TASKW_NOTASK_MSG", default="No Task", arg_type=str)urgency_tf = _default("TASKW_SORT_URGENCY", default="f", arg_type=_strbool)taskw_tf = _default("TASKW_TF", default="t", arg_type=_strbool)timew_tf = _default("TIMEW_TF", default="f", arg_type=_strbool)pending_tasks_tf = _default("TASKW_PENDING_TF", default="f", arg_type=_strbool)timew_desc_override = _default("TIMEW_DESC_OVERRIDE", default="f", arg_type=_strbool)main_filter = _default("TASKW_MAIN_FILTER", default="+ACTIVE", arg_type=str)# Set timew_tf to true if the override is set.if timew_desc_override:timew_tf = True############################### TESTING TESTING TESTING# taskw_tf = False# timew_tf = True# timew_desc_override = True# pending_tasks_tf = True# notask_msg = "~No Task~"############################### text output helper functionsdef shorten(string, maxlen=maxlen):"""Shorten a string to maxlen characters or fewer."""if len(string) <= maxlen:return stringelse:return string[: maxlen - 3] + "..."# taskw functionsdef get_taskw_json(filter_string):"""Take a taskw filter and returns the json output for task export."""return json.loads(subprocess.check_output("task " + filter_string + " export", shell=True))def sort_taskw_info(taskw_json):"""Return task description to display plus number of tasks.Take json output from taskw and return the correct task descriptionto display and also the number of tasks matching the filter."""max_urg = 0if len(taskw_json) > 0:if urgency_tf:for i in range(len(taskw_json)):if taskw_json[i]["urgency"] > taskw_json[max_urg]["urgency"]:max_urg = ireturn taskw_json[max_urg]["description"], len(taskw_json)else:return notask_msg, 0def get_taskw_info(taskw_filter=main_filter):"""Take a filter and return a task description and number of tasks."""j = get_taskw_json(taskw_filter)return sort_taskw_info(j)def export_pending():"""Return number of taskw pending tasks."""return len(get_taskw_json("+PENDING"))# timew functionsdef get_timew_bytes(dom_string):"""Return byte output from calling timew."""try:out = subprocess.check_output("timew get " + dom_string, shell=True)except subprocess.CalledProcessError:out = b""return outdef decode_timew_bytes(in_bytes):"""Take timew byte input and return string.This function also strips the trailing newline."""to_string = in_bytes.decode("utf-8")[:-1]return to_stringdef get_timew_string(dom_string):"""Return string decoded output from calling timew with dom_string."""in_string = get_timew_bytes(dom_string)return decode_timew_bytes(in_string)def get_timew_active():"""Return True if timew has active tracking."""return b"1" in get_timew_bytes("dom.active")def export_timew_description():"""Extract description from timew output.Actually extracts first tag."""timew_txt = get_timew_string("dom.active.tag.1")return timew_txt if get_timew_active() else notask_msgdef pad_time(s):"""Add '0' to number if necessary."""return s if len(s) == 2 else "0" + sdef extract_time(delimiter, input_string):"""Extract number of hours|minutes|seconds from timew output."""match_list = re.findall(r"\d?\d" + delimiter, input_string)return pad_time(match_list[0][:-1]) if len(match_list) > 0 else "00"def translate_timew_string(timew_in_str):"""Turn timew output time into duration in HH:MM format."""duration_hrs = extract_time("H", timew_in_str)duration_mins = extract_time("M", timew_in_str)return duration_hrs + ":" + duration_minsdef main():"""Return string to display based on params."""task_desc = ""task_append = ""timew_duration = ""pending_text = ""if taskw_tf:descr, task_num = get_taskw_info()task_desc = shorten(descr)if task_num > 1:task_append = " + " + str(task_num - 1)if timew_tf:get_string = get_timew_string("dom.active.duration")timew_duration = (translate_timew_string(get_string) + " " if get_timew_active() else "")if timew_desc_override or not taskw_tf:task_desc = shorten(export_timew_description())if pending_tasks_tf:pending_text = f" [{export_pending()}]"bar_text = timew_duration + task_desc + task_append + pending_textreturn bar_textif __name__ == "__main__":print(main())
#!/usr/bin/env python3"""Extracts information from taskwarrior and timewarrior to display in i3block."""# This is taskw.py v0.3.1import subprocessimport jsonimport osimport re# config options codedef _default(name, default="", arg_type=str):"""Set a parameter based on OS variable.Fix the argument type and fall back on given default."""val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)def _strbool(s):"""Return True if argument is t,T,true,TRUE etc."""return s.lower() in ["t", "true", "1"]# I don't know who originally wrote these functions,# but many of the python blocklets in i3blocks-contrib use it.# arch-update added this code on 25 March 2018 and as far as I can tell# this was the earliest use.maxlen = _default("TASKW_MAX_LENGTH", default=35, arg_type=int)notask_msg = _default("TASKW_NOTASK_MSG", default="No Task", arg_type=str)urgency_tf = _default("TASKW_SORT_URGENCY", default="f", arg_type=_strbool)taskw_tf = _default("TASKW_TF", default="t", arg_type=_strbool)timew_tf = _default("TIMEW_TF", default="f", arg_type=_strbool)pending_tasks_tf = _default("TASKW_PENDING_TF", default="f", arg_type=_strbool)timew_desc_override = _default("TIMEW_DESC_OVERRIDE", default="f", arg_type=_strbool)main_filter = _default("TASKW_MAIN_FILTER", default="+ACTIVE", arg_type=str)# Set timew_tf to true if the override is set.if timew_desc_override:timew_tf = True############################### TESTING TESTING TESTING# taskw_tf = False# timew_tf = True# timew_desc_override = True# pending_tasks_tf = True# notask_msg = "~No Task~"############################### text output helper functionsdef shorten(string, maxlen=maxlen):"""Shorten a string to maxlen characters or fewer."""if len(string) <= maxlen:return stringelse:return string[: maxlen - 3] + "..."# taskw functionsdef get_taskw_json(filter_string):"""Take a taskw filter and returns the json output for task export."""return json.loads(subprocess.check_output("task " + filter_string + " export", shell=True))def sort_taskw_info(taskw_json):"""Return task description to display plus number of tasks.Take json output from taskw and return the correct task descriptionto display and also the number of tasks matching the filter."""max_urg = 0if len(taskw_json) > 0:if urgency_tf:for i in range(len(taskw_json)):if taskw_json[i]["urgency"] > taskw_json[max_urg]["urgency"]:max_urg = ireturn taskw_json[max_urg]["description"], len(taskw_json)else:return notask_msg, 0def get_taskw_info(taskw_filter=main_filter):"""Take a filter and return a task description and number of tasks."""j = get_taskw_json(taskw_filter)return sort_taskw_info(j)def export_pending():"""Return number of taskw pending tasks."""return len(get_taskw_json("+PENDING"))# timew functionsdef get_timew_bytes(dom_string):"""Return byte output from calling timew."""try:out = subprocess.check_output("timew get " + dom_string, shell=True)except subprocess.CalledProcessError:out = b""return outdef decode_timew_bytes(in_bytes):"""Take timew byte input and return string.This function also strips the trailing newline."""to_string = in_bytes.decode("utf-8")[:-1]return to_stringdef get_timew_string(dom_string):"""Return string decoded output from calling timew with dom_string."""in_string = get_timew_bytes(dom_string)return decode_timew_bytes(in_string)def get_timew_active():"""Return True if timew has active tracking."""return b"1" in get_timew_bytes("dom.active")def export_timew_description():"""Extract description from timew output.Actually extracts first tag."""timew_txt = get_timew_string("dom.active.tag.1")return timew_txt if get_timew_active() else notask_msgdef pad_time(s):"""Add '0' to number if necessary."""return s if len(s) == 2 else "0" + sdef extract_time(delimiter, input_string):"""Extract number of hours|minutes|seconds from timew output."""match_list = re.findall(r"\d?\d" + delimiter, input_string)return pad_time(match_list[0][:-1]) if len(match_list) > 0 else "00"def translate_timew_string(timew_in_str):"""Turn timew output time into duration in HH:MM format."""duration_hrs = extract_time("H", timew_in_str)duration_mins = extract_time("M", timew_in_str)return duration_hrs + ":" + duration_minsdef main():"""Return string to display based on params."""task_desc = ""task_append = ""timew_duration = ""pending_text = ""if taskw_tf:descr, task_num = get_taskw_info()task_desc = shorten(descr)if task_num > 1:task_append = " + " + str(task_num - 1)if timew_tf:get_string = get_timew_string("dom.active.duration")timew_duration = (translate_timew_string(get_string) + " " if get_timew_active() else "")if timew_desc_override or not taskw_tf:task_desc = shorten(export_timew_description())if pending_tasks_tf:pending_text = f" [{export_pending()}]"bar_text = timew_duration + task_desc + task_append + pending_textreturn bar_textif __name__ == "__main__":print(main())
#!/usr/bin/env bashNODE_URL=${BLOCK_INSTANCE%/}DISK_AVAIL=$(curl -s "$NODE_URL/statistics?t=json" 2>/dev/null| jq -r '.stats."storage_server.disk_avail"')if [[ -n "$DISK_AVAIL" ]] && [[ "$DISK_AVAIL" != "null" ]]; thenDISK_AVAIL=$(echo "$DISK_AVAIL" | awk '{GB=$1/1024/1024/1024if(GB<1000){printf "%.1fG\n", GB}else{printf "%.1fT\n", GB/1024}}')echo "tahoe: $DISK_AVAIL"elseecho "tahoe down"echo "tahoe down"echo "#FF0000"fi
#!/usr/bin/env bashNODE_URL=${BLOCK_INSTANCE%/}DISK_AVAIL=$(curl -s "$NODE_URL/statistics?t=json" 2>/dev/null| jq -r '.stats."storage_server.disk_avail"')if [[ -n "$DISK_AVAIL" ]] && [[ "$DISK_AVAIL" != "null" ]]; thenDISK_AVAIL=$(echo "$DISK_AVAIL" | awk '{GB=$1/1024/1024/1024if(GB<1000){printf "%.1fG\n", GB}else{printf "%.1fT\n", GB/1024}}')echo "tahoe: $DISK_AVAIL"elseecho "tahoe down"echo "tahoe down"echo "#FF0000"fi
#!/usr/bin/env bashif [[ $USER_UNIT == "true" ]]thenbus="--session"elsebus="--system"fiif [[ -z $FAILED_COLOR ]]thenFAILED_COLOR=redfiif [[ -z $INACTIVE_COLOR ]]thenINACTIVE_COLOR=orangefiif [[ -n $ACTIVE_COLOR ]]thenACTIVE_COLOR=" color='$ACTIVE_COLOR'"fi# echo $FAILED_COLORobject_path=$(dbus-send $bus --print-reply --dest=org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager.GetUnit string:"${UNIT_NAME}" | grep -Po '"\K[^"]+')status=$(dbus-send $bus --dest=org.freedesktop.systemd1 --print-reply "$object_path" org.freedesktop.DBus.Properties.Get string:'org.freedesktop.systemd1.Unit' string:'ActiveState' | grep -oP 'string "\K[^"]+')if [[ $status == "failed" ]]thenecho "<span color='$FAILED_COLOR'>$status</span>"elif [[ $status == "inactive" ]]thenecho "<span color='$INACTIVE_COLOR'>$status</span>"elseecho "<span${ACTIVE_COLOR}>$status</span>"fi
#!/usr/bin/env bashif [[ $USER_UNIT == "true" ]]thenbus="--session"elsebus="--system"fiif [[ -z $FAILED_COLOR ]]thenFAILED_COLOR=redfiif [[ -z $INACTIVE_COLOR ]]thenINACTIVE_COLOR=orangefiif [[ -n $ACTIVE_COLOR ]]thenACTIVE_COLOR=" color='$ACTIVE_COLOR'"fi# echo $FAILED_COLORobject_path=$(dbus-send $bus --print-reply --dest=org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager.GetUnit string:"${UNIT_NAME}" | grep -Po '"\K[^"]+')status=$(dbus-send $bus --dest=org.freedesktop.systemd1 --print-reply "$object_path" org.freedesktop.DBus.Properties.Get string:'org.freedesktop.systemd1.Unit' string:'ActiveState' | grep -oP 'string "\K[^"]+')if [[ $status == "failed" ]]thenecho "<span color='$FAILED_COLOR'>$status</span>"elif [[ $status == "inactive" ]]thenecho "<span color='$INACTIVE_COLOR'>$status</span>"elseecho "<span${ACTIVE_COLOR}>$status</span>"fi
#!/bin/bash# The service we want to check or toggle (according to systemctl)SERVICE=$BLOCK_INSTANCE# Colors to displayINACTIVE_COLOR=#888888ACTIVE_COLOR=#22BB22# Exact string to displayACTIVE="<span foreground=\"$ACTIVE_COLOR\">$SERVICE</span>"INACTIVE="<span foreground=\"$INACTIVE_COLOR\"><s>$SERVICE</s></span>"if [ "$( systemctl is-active "$SERVICE" )" != "active" ]thenif [ "$BLOCK_BUTTON" == '1' ]thenif systemctl start "$SERVICE"thenecho "$ACTIVE"fifiecho "$INACTIVE"elseif [ "$BLOCK_BUTTON" == '1' ]thenif systemctl stop "$SERVICE"thenecho "$INACTIVE"fifiecho "$ACTIVE"fi
#!/bin/bash# The service we want to check or toggle (according to systemctl)SERVICE=$BLOCK_INSTANCE# Colors to displayINACTIVE_COLOR=#888888ACTIVE_COLOR=#22BB22# Exact string to displayACTIVE="<span foreground=\"$ACTIVE_COLOR\">$SERVICE</span>"INACTIVE="<span foreground=\"$INACTIVE_COLOR\"><s>$SERVICE</s></span>"if [ "$( systemctl is-active "$SERVICE" )" != "active" ]thenif [ "$BLOCK_BUTTON" == '1' ]thenif systemctl start "$SERVICE"thenecho "$ACTIVE"fifiecho "$INACTIVE"elseif [ "$BLOCK_BUTTON" == '1' ]thenif systemctl stop "$SERVICE"thenecho "$INACTIVE"fifiecho "$ACTIVE"fi
#!/usr/bin/env bashmaxlen=0if [[ $1 ]]; thenmaxlen=$1fialign="center"if [[ $2 ]]; thenalign=$2fiformat() {if [[ $maxlen == 0 ]]; thenecho "$1"return 0filen=${#1}if [[ $len -ge $maxlen ]]; thenecho "${1:0:${maxlen}}"elsepad=$(( maxlen - len ))case "$align" in"center" )pad=$(( pad / 2 ))printf "%*s%s%*s\n" $pad "" "$1" $pad "";;"left" )printf "%s%*s\n" "$1" $pad "";;"right" )printf "%*s%s\n" $pad "" "$1";;esacfi}process() {while read -r LINE; doformat "$LINE"done}swaymsg -t get_tree | jq --unbuffered -r '.. | select(.focused?) | .name' | processsubscribe_query='select(.container.focused and (.change == "focus" or .change == "title")) | .container.name'swaymsg -m -t SUBSCRIBE "['window']" | jq --unbuffered -r "$subscribe_query" | process
#!/usr/bin/env bashmaxlen=0if [[ $1 ]]; thenmaxlen=$1fialign="center"if [[ $2 ]]; thenalign=$2fiformat() {if [[ $maxlen == 0 ]]; thenecho "$1"return 0filen=${#1}if [[ $len -ge $maxlen ]]; thenecho "${1:0:${maxlen}}"elsepad=$(( maxlen - len ))case "$align" in"center" )pad=$(( pad / 2 ))printf "%*s%s%*s\n" $pad "" "$1" $pad "";;"left" )printf "%s%*s\n" "$1" $pad "";;"right" )printf "%*s%s\n" $pad "" "$1";;esacfi}process() {while read -r LINE; doformat "$LINE"done}swaymsg -t get_tree | jq --unbuffered -r '.. | select(.focused?) | .name' | processsubscribe_query='select(.container.focused and (.change == "focus" or .change == "title")) | .container.name'swaymsg -m -t SUBSCRIBE "['window']" | jq --unbuffered -r "$subscribe_query" | process
#!/usr/bin/env bash# Copyright (C) 2020 hseg <gesh@gesh.uni.cx># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------if [[ -z "$INTERFACE" ]] ; thenINTERFACE="${BLOCK_INSTANCE:-wlan0}"fi#------------------------------------------------------------------------# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.# Similarly, if the wifi interface exists but no connection is active, show# nothing[[ ! -d /sys/class/net/"${INTERFACE}"/wireless || \"$(cat /sys/class/net/"$INTERFACE"/operstate)" = 'down' ]] && exit#------------------------------------------------------------------------SSID=$(iw "$INTERFACE" info | awk '/ssid/ {$1=""; print $0}')#------------------------------------------------------------------------echo "$SSID" # full textecho "$SSID" # short textecho "#00FF00" # color
#!/usr/bin/env bash# Copyright (C) 2020 hseg <gesh@gesh.uni.cx># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------if [[ -z "$INTERFACE" ]] ; thenINTERFACE="${BLOCK_INSTANCE:-wlan0}"fi#------------------------------------------------------------------------# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.# Similarly, if the wifi interface exists but no connection is active, show# nothing[[ ! -d /sys/class/net/"${INTERFACE}"/wireless || \"$(cat /sys/class/net/"$INTERFACE"/operstate)" = 'down' ]] && exit#------------------------------------------------------------------------SSID=$(iw "$INTERFACE" info | awk '/ssid/ {$1=""; print $0}')#------------------------------------------------------------------------echo "$SSID" # full textecho "$SSID" # short textecho "#00FF00" # color
#!/usr/bin/env python3import dbusimport sysdef progressBar(perc : float):char = ["░", "▒", "█"]bar = char[2] * int(perc / 0.2)if perc >= 0.99:return bar + char[2]bar += char[1]while len(bar) != 5:bar += char[0]return bardef main():bus = dbus.SessionBus()proxy = bus.get_object('org.mpris.MediaPlayer2.spotifyd','/org/mpris/MediaPlayer2')properties_manager = dbus.Interface(proxy, 'org.freedesktop.DBus.Properties')if properties_manager:if len(sys.argv) > 1:if sys.argv[1] == "1":dbus.Interface(proxy, 'org.mpris.MediaPlayer2.Player').PlayPause()status = properties_manager.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')if status == "Playing" : status = " "else : status = " "current = properties_manager.Get('org.mpris.MediaPlayer2.Player', 'Position')data = properties_manager.Get('org.mpris.MediaPlayer2.Player', 'Metadata')length = data["mpris:length"]title = data["xesam:title"]perc = current / lengthprogress = progressBar(perc)bar = f" [ {title} ] {status} {progress}"print(bar)if __name__ == "__main__":main()
#!/usr/bin/env python3import dbusimport sysdef progressBar(perc : float):char = ["░", "▒", "█"]bar = char[2] * int(perc / 0.2)if perc >= 0.99:return bar + char[2]bar += char[1]while len(bar) != 5:bar += char[0]return bardef main():bus = dbus.SessionBus()proxy = bus.get_object('org.mpris.MediaPlayer2.spotifyd','/org/mpris/MediaPlayer2')properties_manager = dbus.Interface(proxy, 'org.freedesktop.DBus.Properties')if properties_manager:if len(sys.argv) > 1:if sys.argv[1] == "1":dbus.Interface(proxy, 'org.mpris.MediaPlayer2.Player').PlayPause()status = properties_manager.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')if status == "Playing" : status = " "else : status = " "current = properties_manager.Get('org.mpris.MediaPlayer2.Player', 'Position')data = properties_manager.Get('org.mpris.MediaPlayer2.Player', 'Metadata')length = data["mpris:length"]title = data["xesam:title"]perc = current / lengthprogress = progressBar(perc)bar = f" [ {title} ] {status} {progress}"print(bar)if __name__ == "__main__":main()
#!/bin/sh# Copyright (C) 2018 Nikolas De Giorgis <nikolas.degiorgis@gmail.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.IFS=result=`speedtest-cli --bytes --simple`PING=`echo $result | sed -n 1p |cut -d ':' -f2 | cut -d ' ' -f2`DOWN=`echo $result | sed -n 2p |cut -d ':' -f2 | cut -d ' ' -f2`UP=`echo $result | sed -n 3p |cut -d ':' -f2 | cut -d ' ' -f2`echo $PING" ms" $DOWN "MB/s" $UP "MB/s"
#!/bin/sh# Copyright (C) 2018 Nikolas De Giorgis <nikolas.degiorgis@gmail.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.IFS=result=`speedtest-cli --bytes --simple`PING=`echo $result | sed -n 1p |cut -d ':' -f2 | cut -d ' ' -f2`DOWN=`echo $result | sed -n 2p |cut -d ':' -f2 | cut -d ' ' -f2`UP=`echo $result | sed -n 3p |cut -d ':' -f2 | cut -d ' ' -f2`echo $PING" ms" $DOWN "MB/s" $UP "MB/s"
#!/usr/bin/env bash## Use rofi/zenity to change system runstate thanks to systemd.## Note: this currently relies on associative array support in the shell.## Inspired from i3pystatus wiki:# https://github.com/enkore/i3pystatus/wiki/Shutdown-Menu## Copyright 2015 Benjamin Chrétien <chretien at lirmm dot fr>## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.######################################################################## BEGIN CONFIG ######################################################################### Use a custom lock script#LOCKSCRIPT="i3lock-extra -m pixelize"# Colors: FG (foreground), BG (background), HL (highlighted)FG_COLOR="${FG_COLOR:-#bbbbbb}"BG_COLOR="${BG_COLOR:-#111111}"HLFG_COLOR="${HLFG_COLOR:-#111111}"HLBG_COLOR="${HLBG_COLOR:-#bbbbbb}"BORDER_COLOR="${BORDER_COLOR:-#222222}"# Options not related to colorsROFI_TEXT="${ROFI_TEXT:-Menu:}"ROFI_OPTIONS=(${ROFI_OPTIONS:--theme-str 'window {width: 11%; border: 2;} listview {scrollbar: false;}' -location 3})# Zenity optionsZENITY_TITLE="${ZENITY_TITLE:-Menu}"ZENITY_TEXT="${ZENITY_TEXT:-Action:}"ZENITY_OPTIONS=(${ZENITY_OPTIONS:---column= --hide-header})######################################################################## END CONFIG ######################################################################### Whether to ask for user's confirmationenable_confirmation=${ENABLE_CONFIRMATIONS:-false}# Preferred launcher if both are availablepreferred_launcher="${LAUNCHER:-rofi}"usage="$(basename "$0") [-h] [-c] [-p name] -- display a menu for shutdown, reboot, lock etc.where:-h show this help text-c ask for user confirmation-p preferred launcher (rofi or zenity)This script depends on:- systemd,- i3,- rofi or zenity."# Check whether the user-defined launcher is validlauncher_list=(rofi zenity)function check_launcher() {if [[ ! "${launcher_list[@]}" =~ (^|[[:space:]])"$1"($|[[:space:]]) ]]; thenecho "Supported launchers: ${launcher_list[*]}"exit 1else# Get array with unique elements and preferred launcher first# Note: uniq expects a sorted list, so we cannot use iti=1launcher_list=($(for l in "$1" "${launcher_list[@]}"; do printf "%i %s\n" "$i" "$l"; let i+=1; done \| sort -uk2 | sort -nk1 | cut -d' ' -f2- | tr '\n' ' '))fi}# Parse CLI argumentswhile getopts "hcp:" option; docase "${option}" inh) echo "${usage}"exit 0;;c) enable_confirmation=true;;p) preferred_launcher="${OPTARG}"check_launcher "${preferred_launcher}";;*) exit 1;;esacdonecheck_launcher "${preferred_launcher}"# Check whether a command existsfunction command_exists() {command -v "$1" &> /dev/null 2>&1}# systemctl requiredif ! command_exists systemctl ; thenexit 1fi# menu defined as an associative arraytypeset -A menu# Menu with keys/commandsmenu=([Shutdown]="systemctl poweroff"[Reboot]="systemctl reboot"[Hibernate]="systemctl hibernate"[Suspend]="systemctl suspend"[Halt]="systemctl halt"[Lock]="${LOCKSCRIPT:-i3lock --color=${BG_COLOR#"#"}}"[Logout]="i3-msg exit"[Cancel]="")menu_nrows=${#menu[@]}# Menu entries that may trigger a confirmation messagemenu_confirm="Shutdown Reboot Hibernate Suspend Halt Logout"launcher_exe=""launcher_options=""rofi_colors=""function prepare_launcher() {if [[ "$1" == "rofi" ]]; thenrofi_colors=(-bc "${BORDER_COLOR}" -bg "${BG_COLOR}" -fg "${FG_COLOR}" \-hlfg "${HLFG_COLOR}" -hlbg "${HLBG_COLOR}")launcher_exe="rofi"launcher_options=(-dmenu -i -lines "${menu_nrows}" -p "${ROFI_TEXT}" \"${rofi_colors[@]}" "${ROFI_OPTIONS[@]}")elif [[ "$1" == "zenity" ]]; thenlauncher_exe="zenity"launcher_options=(--list --title="${ZENITY_TITLE}" --text="${ZENITY_TEXT}" \"${ZENITY_OPTIONS[@]}")fi}for l in "${launcher_list[@]}"; doif command_exists "${l}" ; thenprepare_launcher "${l}"breakfidone# No launcher availableif [[ -z "${launcher_exe}" ]]; thenexit 1filauncher=(${launcher_exe} "${launcher_options[@]}")selection="$(printf '%s\n' "${!menu[@]}" | sort | "${launcher[@]}")"function ask_confirmation() {if [ "${launcher_exe}" == "rofi" ]; thenconfirmed=$(echo -e "Yes\nNo" | rofi -dmenu -i -lines 2 -p "${selection}?" \"${rofi_colors[@]}" "${ROFI_OPTIONS[@]}")[ "${confirmed}" == "Yes" ] && confirmed=0elif [ "${launcher_exe}" == "zenity" ]; thenzenity --question --text "Are you sure you want to ${selection,,}?"confirmed=$?fiif [ "${confirmed}" == 0 ]; theni3-msg -q "exec ${menu[${selection}]}"fi}if [[ $? -eq 0 && ! -z ${selection} ]]; thenif [[ "${enable_confirmation}" = true && \${menu_confirm} =~ (^|[[:space:]])"${selection}"($|[[:space:]]) ]]; thenask_confirmationelsei3-msg -q "exec ${menu[${selection}]}"fifi
#!/usr/bin/env bash## Use rofi/zenity to change system runstate thanks to systemd.## Note: this currently relies on associative array support in the shell.## Inspired from i3pystatus wiki:# https://github.com/enkore/i3pystatus/wiki/Shutdown-Menu## Copyright 2015 Benjamin Chrétien <chretien at lirmm dot fr>## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.######################################################################## BEGIN CONFIG ######################################################################### Use a custom lock script#LOCKSCRIPT="i3lock-extra -m pixelize"# Colors: FG (foreground), BG (background), HL (highlighted)FG_COLOR="${FG_COLOR:-#bbbbbb}"BG_COLOR="${BG_COLOR:-#111111}"HLFG_COLOR="${HLFG_COLOR:-#111111}"HLBG_COLOR="${HLBG_COLOR:-#bbbbbb}"BORDER_COLOR="${BORDER_COLOR:-#222222}"# Options not related to colorsROFI_TEXT="${ROFI_TEXT:-Menu:}"ROFI_OPTIONS=(${ROFI_OPTIONS:--theme-str 'window {width: 11%; border: 2;} listview {scrollbar: false;}' -location 3})# Zenity optionsZENITY_TITLE="${ZENITY_TITLE:-Menu}"ZENITY_TEXT="${ZENITY_TEXT:-Action:}"ZENITY_OPTIONS=(${ZENITY_OPTIONS:---column= --hide-header})######################################################################## END CONFIG ######################################################################### Whether to ask for user's confirmationenable_confirmation=${ENABLE_CONFIRMATIONS:-false}# Preferred launcher if both are availablepreferred_launcher="${LAUNCHER:-rofi}"usage="$(basename "$0") [-h] [-c] [-p name] -- display a menu for shutdown, reboot, lock etc.where:-h show this help text-c ask for user confirmation-p preferred launcher (rofi or zenity)This script depends on:- systemd,- i3,- rofi or zenity."# Check whether the user-defined launcher is validlauncher_list=(rofi zenity)function check_launcher() {if [[ ! "${launcher_list[@]}" =~ (^|[[:space:]])"$1"($|[[:space:]]) ]]; thenecho "Supported launchers: ${launcher_list[*]}"exit 1else# Get array with unique elements and preferred launcher first# Note: uniq expects a sorted list, so we cannot use iti=1launcher_list=($(for l in "$1" "${launcher_list[@]}"; do printf "%i %s\n" "$i" "$l"; let i+=1; done \| sort -uk2 | sort -nk1 | cut -d' ' -f2- | tr '\n' ' '))fi}# Parse CLI argumentswhile getopts "hcp:" option; docase "${option}" inh) echo "${usage}"exit 0;;c) enable_confirmation=true;;p) preferred_launcher="${OPTARG}"check_launcher "${preferred_launcher}";;*) exit 1;;esacdonecheck_launcher "${preferred_launcher}"# Check whether a command existsfunction command_exists() {command -v "$1" &> /dev/null 2>&1}# systemctl requiredif ! command_exists systemctl ; thenexit 1fi# menu defined as an associative arraytypeset -A menu# Menu with keys/commandsmenu=([Shutdown]="systemctl poweroff"[Reboot]="systemctl reboot"[Hibernate]="systemctl hibernate"[Suspend]="systemctl suspend"[Halt]="systemctl halt"[Lock]="${LOCKSCRIPT:-i3lock --color=${BG_COLOR#"#"}}"[Logout]="i3-msg exit"[Cancel]="")menu_nrows=${#menu[@]}# Menu entries that may trigger a confirmation messagemenu_confirm="Shutdown Reboot Hibernate Suspend Halt Logout"launcher_exe=""launcher_options=""rofi_colors=""function prepare_launcher() {if [[ "$1" == "rofi" ]]; thenrofi_colors=(-bc "${BORDER_COLOR}" -bg "${BG_COLOR}" -fg "${FG_COLOR}" \-hlfg "${HLFG_COLOR}" -hlbg "${HLBG_COLOR}")launcher_exe="rofi"launcher_options=(-dmenu -i -lines "${menu_nrows}" -p "${ROFI_TEXT}" \"${rofi_colors[@]}" "${ROFI_OPTIONS[@]}")elif [[ "$1" == "zenity" ]]; thenlauncher_exe="zenity"launcher_options=(--list --title="${ZENITY_TITLE}" --text="${ZENITY_TEXT}" \"${ZENITY_OPTIONS[@]}")fi}for l in "${launcher_list[@]}"; doif command_exists "${l}" ; thenprepare_launcher "${l}"breakfidone# No launcher availableif [[ -z "${launcher_exe}" ]]; thenexit 1filauncher=(${launcher_exe} "${launcher_options[@]}")selection="$(printf '%s\n' "${!menu[@]}" | sort | "${launcher[@]}")"function ask_confirmation() {if [ "${launcher_exe}" == "rofi" ]; thenconfirmed=$(echo -e "Yes\nNo" | rofi -dmenu -i -lines 2 -p "${selection}?" \"${rofi_colors[@]}" "${ROFI_OPTIONS[@]}")[ "${confirmed}" == "Yes" ] && confirmed=0elif [ "${launcher_exe}" == "zenity" ]; thenzenity --question --text "Are you sure you want to ${selection,,}?"confirmed=$?fiif [ "${confirmed}" == 0 ]; theni3-msg -q "exec ${menu[${selection}]}"fi}if [[ $? -eq 0 && ! -z ${selection} ]]; thenif [[ "${enable_confirmation}" = true && \${menu_confirm} =~ (^|[[:space:]])"${selection}"($|[[:space:]]) ]]; thenask_confirmationelsei3-msg -q "exec ${menu[${selection}]}"fifi
#! /usr/bin/env bash###### Variables ######LABEL="${LABEL:- }"LOCATION="${LOCATION:- }"FONT="${FONT:-Monospace 10}"ROFI_CONFIG_FILE="${ROFI_CONFIG_FILE:-/dev/null}"BAR_POSITION="${BAR_POSITION:-bottom}"###### Variables ############ Functions ####### print the full weather# see https://github.com/chubin/wttr.in#usage for full configuration optionsprint_weather_report() {if [[ $LOCATION != " " ]]; thencurl https://wttr.in/$LOCATION?Telsecurl https://wttr.in/?Tfi}# print the one line weather# see https://github.com/chubin/wttr.in#one-line-output for formatting optionsprint_weather_line() {if [[ $LOCATION != " " ]]; thencurl -s https://wttr.in/${LOCATION}?u\&format="%C+%c+%t+(%f)+%w" | tr -d \"elsecurl -s 'https://wttr.in/?u\&format="%C+%c+%t+(%f)+%w"' | tr -d \"fi}###### Functions ############ Main body ####### handle any click# rofi pop upcase "$BLOCK_BUTTON" in1|2|3)IFS=weather_report=$(print_weather_report)# check bar position and adjust anchor accordinglyif [[ $BAR_POSITION = "top" ]]; thenanchor="northwest"elseanchor="southwest"fi# open rofi# (add the following option to rofi command with proper config file, if needed)echo $weather_report \| rofi \-dmenu \-markup-rows \-font $FONT \-m -3 \-theme-str 'window {width: 53%; anchor: '"$anchor"'; location: northwest;}' \-theme-str 'listview {lines: '"$(echo $weather_report | wc -l)"' ;scrollbar: false;}' \-theme $ROFI_CONFIG_FILE \-p "Detailed weather report"esac# print blocklet textif [[ $LABEL != " " ]]; thenecho $LABEL$(print_weather_line)elseecho $(print_weather_line)fi###### Main body ######
#! /usr/bin/env bash###### Variables ######LABEL="${LABEL:- }"LOCATION="${LOCATION:- }"FONT="${FONT:-Monospace 10}"ROFI_CONFIG_FILE="${ROFI_CONFIG_FILE:-/dev/null}"BAR_POSITION="${BAR_POSITION:-bottom}"###### Variables ############ Functions ####### print the full weather# see https://github.com/chubin/wttr.in#usage for full configuration optionsprint_weather_report() {if [[ $LOCATION != " " ]]; thencurl https://wttr.in/$LOCATION?Telsecurl https://wttr.in/?Tfi}# print the one line weather# see https://github.com/chubin/wttr.in#one-line-output for formatting optionsprint_weather_line() {if [[ $LOCATION != " " ]]; thencurl -s https://wttr.in/${LOCATION}?u\&format="%C+%c+%t+(%f)+%w" | tr -d \"elsecurl -s 'https://wttr.in/?u\&format="%C+%c+%t+(%f)+%w"' | tr -d \"fi}###### Functions ############ Main body ####### handle any click# rofi pop upcase "$BLOCK_BUTTON" in1|2|3)IFS=weather_report=$(print_weather_report)# check bar position and adjust anchor accordinglyif [[ $BAR_POSITION = "top" ]]; thenanchor="northwest"elseanchor="southwest"fi# open rofi# (add the following option to rofi command with proper config file, if needed)echo $weather_report \| rofi \-dmenu \-markup-rows \-font $FONT \-m -3 \-theme-str 'window {width: 53%; anchor: '"$anchor"'; location: northwest;}' \-theme-str 'listview {lines: '"$(echo $weather_report | wc -l)"' ;scrollbar: false;}' \-theme $ROFI_CONFIG_FILE \-p "Detailed weather report"esac# print blocklet textif [[ $LABEL != " " ]]; thenecho $LABEL$(print_weather_line)elseecho $(print_weather_line)fi###### Main body ######
#! /usr/bin/env bash###### Variables ######DATEFTM="${DATEFTM:-+%a %d %b %Y}"SHORTFMT="${SHORTFMT:-+%d/%m/%Y}"LABEL="${LABEL:- }"FONT="${FONT:-Monospace 10}"LEFTCLICK_PREV_MONTH=${LEFTCLICK_PREV_MONTH:-false}PREV_MONTH_TEXT="${PREV_MONTH_TEXT:-« previous month «}"NEXT_MONTH_TEXT="${NEXT_MONTH_TEXT:-» next month »}"ROFI_CONFIG_FILE="${ROFI_CONFIG_FILE:-/dev/null}"BAR_POSITION="${BAR_POSITION:-bottom}"WEEK_START="${WEEK_START:-monday}"###### Variables ############ Functions ####### get current date and set today headerget_current_date() {year=$(date '+%Y')month=$(date '+%m')day=$(date '+%d')}# print the selected monthprint_month() {mnt=$1yr=$2cal --color=always --$WEEK_START $mnt $yr \| sed -e 's/\x1b\[[7;]*m/\<b\>\<u\>/g' \-e 's/\x1b\[[27;]*m/\<\/u\>\<\/b\>/g' \-e '/^ *$/d' \| tail -n +2echo $PREV_MONTH_TEXT$'\n'$NEXT_MONTH_TEXT}# increment year and/or month appropriately based on month incrementincrement_month() {# pick increment and define/update deltaincr=$1(( delta += incr ))# for non-current monthif (( incr != 0 )); then# add the incrementmonth=$(( 10#$month + incr ))# normalize month and compute yearif (( month > 0 )); then(( month -= 1 ))(( year += month/12 ))(( month %= 12 ))(( month += 1 ))else(( year += month/12 - 1 ))(( month %= 12 ))(( month += 12 ))fifi# adjust headerif (( delta == 0 )); then# today's month => show dd/mm/yyyyheader=$(date "$DATEFTM")else# not today's month => show mm/yyyyheader=$(cal $month $year | sed -n '1s/^ *\(.*[^ ]\) *$/\1/p')fi}###### Functions ############ Main body ######get_current_date# handle the click# variables:# current_row: set means today row is highlighted# current_row: not set means...# bias_row == 0: `next month` row is highlighted# bias_row == -1: `prev month` row is highlighted# selected: contains the selected row (next or prev month)# month_page: the month to be printedcase "$BLOCK_BUTTON" in1)if [[ $LEFTCLICK_PREV_MONTH == true ]]; thenincrement_month -1bias_row=-1elseincrement_month 0current_row=fi;;2)increment_month 0current_row=;;3)increment_month +1bias_row=0;;esac# rofi pop upcase "$BLOCK_BUTTON" in1|2|3)# as long as prev/next is selected (and the first time also)while [[ "${selected+xxx}" != "xxx" ]] || [[ $selected =~ ($PREV_MONTH_TEXT|$NEXT_MONTH_TEXT) ]]; doIFS=month_page=$(print_month $month $year)if [[ "${current_row+xxx}" = "xxx" ]]; thencurrent_row=$(( $(echo $month_page | grep -n ${day#0} | head -n 1 | cut -d: -f1) - 1 ))elsecurrent_row=$(( $(echo $month_page | wc -l) - 1))fi# check bar position and adjust anchor accordinglyif [[ $BAR_POSITION = "top" ]]; thenanchor="northeast"elseanchor="southeast"fi# open rofi and read the selected row# (add the following option to rofi command with proper config file, if needed)selected="$(echo $month_page \| rofi \-dmenu \-markup-rows \-font $FONT \-m -3 \-theme-str 'window {width: 10%; anchor: '"$anchor"'; location: northwest;}' \-theme-str 'listview {lines: '"$(echo $month_page | wc -l)"' ;scrollbar: false;}' \-theme $ROFI_CONFIG_FILE \-selected-row $(( current_row + bias_row )) \-p "$header")"# select next/prev month if necessary and prepare row to be highlighted[[ $selected =~ $PREV_MONTH_TEXT ]] && { increment_month -1; bias_row=-1; }[[ $selected =~ $NEXT_MONTH_TEXT ]] && { increment_month +1; bias_row=0; }# get ready for successive next/prev month hitsunset current_rowdoneesac# print blocklet textecho $LABEL$(date "$DATEFTM")echo $LABEL$(date "$SHORTFMT")###### Main body ######
#! /usr/bin/env bash###### Variables ######DATEFTM="${DATEFTM:-+%a %d %b %Y}"SHORTFMT="${SHORTFMT:-+%d/%m/%Y}"LABEL="${LABEL:- }"FONT="${FONT:-Monospace 10}"LEFTCLICK_PREV_MONTH=${LEFTCLICK_PREV_MONTH:-false}PREV_MONTH_TEXT="${PREV_MONTH_TEXT:-« previous month «}"NEXT_MONTH_TEXT="${NEXT_MONTH_TEXT:-» next month »}"ROFI_CONFIG_FILE="${ROFI_CONFIG_FILE:-/dev/null}"BAR_POSITION="${BAR_POSITION:-bottom}"WEEK_START="${WEEK_START:-monday}"###### Variables ############ Functions ####### get current date and set today headerget_current_date() {year=$(date '+%Y')month=$(date '+%m')day=$(date '+%d')}# print the selected monthprint_month() {mnt=$1yr=$2cal --color=always --$WEEK_START $mnt $yr \| sed -e 's/\x1b\[[7;]*m/\<b\>\<u\>/g' \-e 's/\x1b\[[27;]*m/\<\/u\>\<\/b\>/g' \-e '/^ *$/d' \| tail -n +2echo $PREV_MONTH_TEXT$'\n'$NEXT_MONTH_TEXT}# increment year and/or month appropriately based on month incrementincrement_month() {# pick increment and define/update deltaincr=$1(( delta += incr ))# for non-current monthif (( incr != 0 )); then# add the incrementmonth=$(( 10#$month + incr ))# normalize month and compute yearif (( month > 0 )); then(( month -= 1 ))(( year += month/12 ))(( month %= 12 ))(( month += 1 ))else(( year += month/12 - 1 ))(( month %= 12 ))(( month += 12 ))fifi# adjust headerif (( delta == 0 )); then# today's month => show dd/mm/yyyyheader=$(date "$DATEFTM")else# not today's month => show mm/yyyyheader=$(cal $month $year | sed -n '1s/^ *\(.*[^ ]\) *$/\1/p')fi}###### Functions ############ Main body ######get_current_date# handle the click# variables:# current_row: set means today row is highlighted# current_row: not set means...# bias_row == 0: `next month` row is highlighted# bias_row == -1: `prev month` row is highlighted# selected: contains the selected row (next or prev month)# month_page: the month to be printedcase "$BLOCK_BUTTON" in1)if [[ $LEFTCLICK_PREV_MONTH == true ]]; thenincrement_month -1bias_row=-1elseincrement_month 0current_row=fi;;2)increment_month 0current_row=;;3)increment_month +1bias_row=0;;esac# rofi pop upcase "$BLOCK_BUTTON" in1|2|3)# as long as prev/next is selected (and the first time also)while [[ "${selected+xxx}" != "xxx" ]] || [[ $selected =~ ($PREV_MONTH_TEXT|$NEXT_MONTH_TEXT) ]]; doIFS=month_page=$(print_month $month $year)if [[ "${current_row+xxx}" = "xxx" ]]; thencurrent_row=$(( $(echo $month_page | grep -n ${day#0} | head -n 1 | cut -d: -f1) - 1 ))elsecurrent_row=$(( $(echo $month_page | wc -l) - 1))fi# check bar position and adjust anchor accordinglyif [[ $BAR_POSITION = "top" ]]; thenanchor="northeast"elseanchor="southeast"fi# open rofi and read the selected row# (add the following option to rofi command with proper config file, if needed)selected="$(echo $month_page \| rofi \-dmenu \-markup-rows \-font $FONT \-m -3 \-theme-str 'window {width: 10%; anchor: '"$anchor"'; location: northwest;}' \-theme-str 'listview {lines: '"$(echo $month_page | wc -l)"' ;scrollbar: false;}' \-theme $ROFI_CONFIG_FILE \-selected-row $(( current_row + bias_row )) \-p "$header")"# select next/prev month if necessary and prepare row to be highlighted[[ $selected =~ $PREV_MONTH_TEXT ]] && { increment_month -1; bias_row=-1; }[[ $selected =~ $NEXT_MONTH_TEXT ]] && { increment_month +1; bias_row=0; }# get ready for successive next/prev month hitsunset current_rowdoneesac# print blocklet textecho $LABEL$(date "$DATEFTM")echo $LABEL$(date "$SHORTFMT")###### Main body ######
#!/bin/perl# For temperature: subtract 8 from the F value for the actual temperature# Get PurpleAir sensor IDif ($ENV{'SENSOR_ID'} == "") {print STDERR "Missing required environment variable 'SENSOR_ID'.\n";exit 1;}$sensor_id = $ENV{'SENSOR_ID'};# Get measurement type. Default: US_AQI@valid_types = ("US_AQI", "EU_AQI", "CA_AQHI", "IMECA", "IAS");$type = 'US_AQI';if (grep(/^$ENV{'TYPE'}$/, @valid_types)) {$type = $ENV{'TYPE'};} elsif ($ENV{'TYPE'}) {print STDERR "Unrecognized TYPE: $ENV{'TYPE'}. Valid values are: [@valid_types]";exit 1;}# Read pm2.5 10-minute average from the PurpleAir sensor$pm2_5 = `curl "http://purpleair.com/json?show=$sensor_id" 2>/dev/null \\| jq -r '.results | map(select(has("Stats")) | .Stats | fromjson | .v1) | add / length'`;#################### IMPLEMENTATIONS ####################sub UsAqi {# See https://forum.airnowtech.org/t/the-aqi-equation/169## PM2.5 | ConcLo | ConcHi | AQILo | AQIHi# Good | 0.0 | 12.0 | 0 | 50# Moderate | 12.1 | 35.4 | 51 | 100# Unhealthy Sensitive | 35.5 | 55.4 | 101 | 150# Unhealthy | 55.5 | 150.4 | 151 | 200# Very Unhealthy | 150.5 | 250.4 | 201 | 300# Hazardous | 250.5 | 500.4 | 301 | 500## |------------Multiplier-----------| Threshold Addition# (AQIHi - AQILo) / (ConcHi - ConcLo) * (ConcNow - ConcLo) + AQILo@colors = ("#00e400", "#ffff00", "#ff7e00", "#ff0000", "#8f3f97", "#7e0023");$pm2_5 = $_[0];# Table of values: Threshold, Multiplier, Addition@t = ([0.0, 4.1667, 0.0],[12.1, 2.1030, 51],[35.5, 2.4623, 101],[55.5, 0.5163, 151],[150.5, 0.9910, 201],[250.5, 0.7963, 301]);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 5; $i >= 0; $i--) {if ($pm2_5 >= $t[$i][0]) {$r = $i;last;}}# Compute AQI from raw pm2.5 concentration$aqi = $t[$r][1] * ($pm2_5 - $t[$r][0]) + $t[$r][2];return ('val' => sprintf("%.0f", $aqi),'colors' => [@colors],'color_idx' => $r);}sub EuAqi {# See https://airindex.eea.europa.eu/Map/AQI/Viewer/# European Air Quality Index uses the pm2.5 concentration directly.@colors = ("#50f0e6", "#50ccaa", "#f0e641", "#ff5050", "#960032", "#7d2181");$pm2_5 = $_[0];# Thresholds for color indices@t = (0.0, 10.0, 20.0, 25.0, 50.0, 75.0);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 5; $i >= 0; $i--) {if ($pm2_5 >= $t[$i]) {$r = $i;last;}}return ('val' => sprintf("%.0f", $pm2_5),'colors' => [@colors],'color_idx' => $r);}sub CaAqhi {# See https://en.wikipedia.org/wiki/Air_Quality_Health_Index_(Canada)#Calculation# Note: AQHI should also incorporate O3 and NO2, but PurpleAir only has PM2.5# The pm2.5 calculation is used alone and multiplied by 3.# 1-3: Low# 4-6: Moderate# 7-10: High# 11+: Very High@colors = ("#00ccff", "#0099cc", "#006699","#ffff00", "#ffcc00", "#ff9933","#ff6666", "#ff0000", "#cc0000","#990000", "#660000");$pm2_5 = $_[0];$aqhi = 3 * 1000 / 10.4 * ((exp(0.000487 * $pm2_5) - 1));return ('val' => sprintf("%.0f", $aqhi >= 1 ? $aqhi : 1),'colors' => [@colors],'color_idx' => $r);}sub Imeca {# See http://rama.edomex.gob.mx/imeca## PM2.5 | Threshold | Multiplier | Addition# Buena | 0.0 | 4.17 | 0# Regular | 12.1 | 1.49 | 51# Mala | 45.1 | 0.94 | 101# Muy Mala | 97.5 | 0.93 | 151# Extremadamente Mala | 150.5 | 0.99 | 201# Extremadamente Mala | 250.5 | 0.99 | 301# Extremadamente Mala | 350.5 | 0.66 | 401## Multiplier * (pm2.5 - Threshold) + Addition@colors = ("#00e400", "#ffff00", "#ff7e00", "#ff0000", "#99004c", "#99004c", "#99004c");$pm2_5 = $_[0];# Table of values: Threshold, Multiplier, Addition@t = ([0.0, 4.17, 0.0],[12.1, 1.49, 51.0],[45.1, 0.94, 101.0],[97.5, 0.93, 151.0],[150.5, 0.99, 201.0],[250.5, 0.99, 301.0],[350.5, 0.66, 401.0]);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 6; $i >= 0; $i--) {if ($pm2_5 >= $t[$i][0]) {$r = $i;last;}}# Compute AQI from raw pm2.5 concentration$aqi = $t[$r][1] * ($pm2_5 - $t[$r][0]) + $t[$r][2];return ('val' => sprintf("%.0f", $aqi),'colors' => [@colors],'color_idx' => $r);}sub Ias {# See https://www.dof.gob.mx/nota_detalle_popup.php?codigo=5576807# Índice de aire y salud uses the pm2.5 concentration directly.@colors = ("#00e400", "#ffff00", "#ff7e00", "#ff0000", "#99004c");$pm2_5 = $_[0];# Thresholds for color indices@t = (0.0, 26.0, 46.0, 80.0, 148.0);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 4; $i >= 0; $i--) {if ($pm2_5 >= $t[$i]) {$r = $i;last;}}return ('val' => sprintf("%.0f", $pm2_5),'colors' => [@colors],'color_idx' => $r);}################### OUTPUT RESULTS #################### Compute requested value# Expected return value is a hash of the form:# (# 'val' => <numeric measurement value>,# 'colors' => [<color hex codes>],# 'color_idx' => <0-based index of color array>,# )if ($type eq "US_AQI") {%result = UsAqi($pm2_5);} elsif ($type eq "EU_AQI") {%result = EuAqi($pm2_5);} elsif ($type eq "CA_AQHI") {%result = CaAqhi($pm2_5);} elsif ($type eq "IMECA") {%result = Imeca($pm2_5);} elsif ($type eq "IAS") {%result = Ias($pm2_5);} else {# It should not be possible to reach here.%result = ('val' => 'ERR','colors' => ("#ff0000"),'color_idx' => 0,'num_colors' => 1);}# Get color overrides, if any.if ($ENV{'COLORS'}) {@colors = split(',', $ENV{'COLORS'});if (scalar(@colors) < scalar(@{ $result{'colors'} })) {print STDERR "Warning: number of color overrides is fewer than the number"." of buckets in type $type\n";}} else {@colors = @{ $result{'colors'} };}# Adjust color index if greater than colors length$color_idx = $result{'color_idx'};if ($color_idx >= scalar(@colors)) {$color_idx = scalar(@colors) - 1;}# Full text, short text, colorprint "$result{'val'}\n";print "$result{'val'}\n";if (!$ENV{'NO_COLOR'}) {print "$colors[$color_idx]\n";}
#!/bin/perl# For temperature: subtract 8 from the F value for the actual temperature# Get PurpleAir sensor IDif ($ENV{'SENSOR_ID'} == "") {print STDERR "Missing required environment variable 'SENSOR_ID'.\n";exit 1;}$sensor_id = $ENV{'SENSOR_ID'};# Get measurement type. Default: US_AQI@valid_types = ("US_AQI", "EU_AQI", "CA_AQHI", "IMECA", "IAS");$type = 'US_AQI';if (grep(/^$ENV{'TYPE'}$/, @valid_types)) {$type = $ENV{'TYPE'};} elsif ($ENV{'TYPE'}) {print STDERR "Unrecognized TYPE: $ENV{'TYPE'}. Valid values are: [@valid_types]";exit 1;}# Read pm2.5 10-minute average from the PurpleAir sensor$pm2_5 = `curl "http://purpleair.com/json?show=$sensor_id" 2>/dev/null \\| jq -r '.results | map(select(has("Stats")) | .Stats | fromjson | .v1) | add / length'`;#################### IMPLEMENTATIONS ####################sub UsAqi {# See https://forum.airnowtech.org/t/the-aqi-equation/169## PM2.5 | ConcLo | ConcHi | AQILo | AQIHi# Good | 0.0 | 12.0 | 0 | 50# Moderate | 12.1 | 35.4 | 51 | 100# Unhealthy Sensitive | 35.5 | 55.4 | 101 | 150# Unhealthy | 55.5 | 150.4 | 151 | 200# Very Unhealthy | 150.5 | 250.4 | 201 | 300# Hazardous | 250.5 | 500.4 | 301 | 500## |------------Multiplier-----------| Threshold Addition# (AQIHi - AQILo) / (ConcHi - ConcLo) * (ConcNow - ConcLo) + AQILo@colors = ("#00e400", "#ffff00", "#ff7e00", "#ff0000", "#8f3f97", "#7e0023");$pm2_5 = $_[0];# Table of values: Threshold, Multiplier, Addition@t = ([0.0, 4.1667, 0.0],[12.1, 2.1030, 51],[35.5, 2.4623, 101],[55.5, 0.5163, 151],[150.5, 0.9910, 201],[250.5, 0.7963, 301]);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 5; $i >= 0; $i--) {if ($pm2_5 >= $t[$i][0]) {$r = $i;last;}}# Compute AQI from raw pm2.5 concentration$aqi = $t[$r][1] * ($pm2_5 - $t[$r][0]) + $t[$r][2];return ('val' => sprintf("%.0f", $aqi),'colors' => [@colors],'color_idx' => $r);}sub EuAqi {# See https://airindex.eea.europa.eu/Map/AQI/Viewer/# European Air Quality Index uses the pm2.5 concentration directly.@colors = ("#50f0e6", "#50ccaa", "#f0e641", "#ff5050", "#960032", "#7d2181");$pm2_5 = $_[0];# Thresholds for color indices@t = (0.0, 10.0, 20.0, 25.0, 50.0, 75.0);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 5; $i >= 0; $i--) {if ($pm2_5 >= $t[$i]) {$r = $i;last;}}return ('val' => sprintf("%.0f", $pm2_5),'colors' => [@colors],'color_idx' => $r);}sub CaAqhi {# See https://en.wikipedia.org/wiki/Air_Quality_Health_Index_(Canada)#Calculation# Note: AQHI should also incorporate O3 and NO2, but PurpleAir only has PM2.5# The pm2.5 calculation is used alone and multiplied by 3.# 1-3: Low# 4-6: Moderate# 7-10: High# 11+: Very High@colors = ("#00ccff", "#0099cc", "#006699","#ffff00", "#ffcc00", "#ff9933","#ff6666", "#ff0000", "#cc0000","#990000", "#660000");$pm2_5 = $_[0];$aqhi = 3 * 1000 / 10.4 * ((exp(0.000487 * $pm2_5) - 1));return ('val' => sprintf("%.0f", $aqhi >= 1 ? $aqhi : 1),'colors' => [@colors],'color_idx' => $r);}sub Imeca {# See http://rama.edomex.gob.mx/imeca## PM2.5 | Threshold | Multiplier | Addition# Buena | 0.0 | 4.17 | 0# Regular | 12.1 | 1.49 | 51# Mala | 45.1 | 0.94 | 101# Muy Mala | 97.5 | 0.93 | 151# Extremadamente Mala | 150.5 | 0.99 | 201# Extremadamente Mala | 250.5 | 0.99 | 301# Extremadamente Mala | 350.5 | 0.66 | 401## Multiplier * (pm2.5 - Threshold) + Addition@colors = ("#00e400", "#ffff00", "#ff7e00", "#ff0000", "#99004c", "#99004c", "#99004c");$pm2_5 = $_[0];# Table of values: Threshold, Multiplier, Addition@t = ([0.0, 4.17, 0.0],[12.1, 1.49, 51.0],[45.1, 0.94, 101.0],[97.5, 0.93, 151.0],[150.5, 0.99, 201.0],[250.5, 0.99, 301.0],[350.5, 0.66, 401.0]);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 6; $i >= 0; $i--) {if ($pm2_5 >= $t[$i][0]) {$r = $i;last;}}# Compute AQI from raw pm2.5 concentration$aqi = $t[$r][1] * ($pm2_5 - $t[$r][0]) + $t[$r][2];return ('val' => sprintf("%.0f", $aqi),'colors' => [@colors],'color_idx' => $r);}sub Ias {# See https://www.dof.gob.mx/nota_detalle_popup.php?codigo=5576807# Índice de aire y salud uses the pm2.5 concentration directly.@colors = ("#00e400", "#ffff00", "#ff7e00", "#ff0000", "#99004c");$pm2_5 = $_[0];# Thresholds for color indices@t = (0.0, 26.0, 46.0, 80.0, 148.0);# Find relevant row for computation based on pm2.5 thresholdfor ($i = 4; $i >= 0; $i--) {if ($pm2_5 >= $t[$i]) {$r = $i;last;}}return ('val' => sprintf("%.0f", $pm2_5),'colors' => [@colors],'color_idx' => $r);}################### OUTPUT RESULTS #################### Compute requested value# Expected return value is a hash of the form:# (# 'val' => <numeric measurement value>,# 'colors' => [<color hex codes>],# 'color_idx' => <0-based index of color array>,# )if ($type eq "US_AQI") {%result = UsAqi($pm2_5);} elsif ($type eq "EU_AQI") {%result = EuAqi($pm2_5);} elsif ($type eq "CA_AQHI") {%result = CaAqhi($pm2_5);} elsif ($type eq "IMECA") {%result = Imeca($pm2_5);} elsif ($type eq "IAS") {%result = Ias($pm2_5);} else {# It should not be possible to reach here.%result = ('val' => 'ERR','colors' => ("#ff0000"),'color_idx' => 0,'num_colors' => 1);}# Get color overrides, if any.if ($ENV{'COLORS'}) {@colors = split(',', $ENV{'COLORS'});if (scalar(@colors) < scalar(@{ $result{'colors'} })) {print STDERR "Warning: number of color overrides is fewer than the number"." of buckets in type $type\n";}} else {@colors = @{ $result{'colors'} };}# Adjust color index if greater than colors length$color_idx = $result{'color_idx'};if ($color_idx >= scalar(@colors)) {$color_idx = scalar(@colors) - 1;}# Full text, short text, colorprint "$result{'val'}\n";print "$result{'val'}\n";if (!$ENV{'NO_COLOR'}) {print "$colors[$color_idx]\n";}
#!/usr/bin/env perluse strict;use warnings;use utf8;use JSON::Parse 'parse_json';my $units = parse_json(`systemctl list-units --output=json --state=active 'openvpn-client@*'`);if (@$units) {my @names = sort map {$_->{unit} =~ /^openvpn-client@(.*)\.service$/;$1;} @$units;print join(' ', @names) . "\n";print "up\n";print "#00FF00\n";} else {print "down\n";print "down\n";print "#FF0000\n";}
#!/usr/bin/env perluse strict;use warnings;use utf8;use JSON::Parse 'parse_json';my $units = parse_json(`systemctl list-units --output=json --state=active 'openvpn-client@*'`);if (@$units) {my @names = sort map {$_->{unit} =~ /^openvpn-client@(.*)\.service$/;$1;} @$units;print join(' ', @names) . "\n";print "up\n";print "#00FF00\n";} else {print "down\n";print "down\n";print "#FF0000\n";}
#!/usr/bin/env perl# Made by Pierre Mavro/Deimosfr <deimos@deimos.fr># Minor contribution by Thor K. H. <thor@roht.no># Licensed under the terms of the GNU GPL v3, or any later version.# Version: 0.3# Usage:# 1. The configuration name of OpenVPN should be familiar for you (home,work...)# 2. The device name in your configuration file should be fully named (tun0,tap1...not only tun or tap)# 3. When you launch one or multiple OpenVPN connexion, be sure the PID file is written in the correct folder (ex: --writepid /run/openvpn/home.pid)use strict;use warnings;use utf8;use Getopt::Long;my $openvpn_enabled='/dev/shm/openvpn_i3blocks_enabled';my $openvpn_disabled='/dev/shm/openvpn_i3blocks_disabled';# Print outputsub print_output {my $ref_pid_files = shift;my @pid_files = @$ref_pid_files;my $change=0;# Total pid filesmy $total_pid = @pid_files;if ($total_pid == 0) {print "down\n"x2;# Delete OpenVPN i3blocks temp filesif (-f $openvpn_enabled) {unlink $openvpn_enabled or die "Can't delete $openvpn_enabled\n";# Colorize if VPN has just went downprint '#FF0000\n';}unless (-f $openvpn_disabled) {open(my $shm, '>', $openvpn_disabled) or die "Can't write $openvpn_disabled\n";}exit(0);}# Check if interface device is presentmy $vpn_found=0;my $pid;my $cmd_line;my @config_name;my @config_path;my $interface;my $config_prefix;my $current_config_path;my $current_config_name;foreach (@pid_files) {# Get current PID$pid=0;open(PID, '<', $_);while(<PID>) {chomp $_;$pid = $_;}close(PID);# Check if PID has been foundif ($pid ==0) {print "Can't get PID $_: $!\n";}# Check if PID is still alive$cmd_line='/proc/'.$pid.'/cmdline';if (-f $cmd_line) {# Get config nameopen(CMD_LINE, '<', $cmd_line);while(<CMD_LINE>) {chomp $_;$config_prefix = "";if ($_ =~ /--cd\x{00}(.*?)\x{00}/) {$config_prefix = $1;}if ($_ =~ /--config\x{00}(.*?\.conf)\x{00}/) {# Get interface from config file$current_config_path = $1;# Remove unwanted escape chars$interface = 'null';# Get configuration nameif ($current_config_path =~ /(\w+).conf/) {$current_config_name=$1;} else {$current_config_name='unknown';}$current_config_path = "$config_prefix/$current_config_path";# Get OpenVPN interface device nameopen(CONFIG, '<', $current_config_path) or die "Can't read config file '$current_config_path': $!\n";while(<CONFIG>) {chomp $_;if ($_ =~ /dev\s+(\w+)/) {$interface=$1;last;}}close(CONFIG);# check if interface existunless ($interface eq 'null') {if (-d "/sys/class/net/$interface") {push @config_name, $current_config_name;$vpn_found=1;# Write enabled fileunless (-f $openvpn_enabled) {open(my $shm, '>', $openvpn_enabled) or die "Can't write $openvpn_enabled\n";$change=1;}}}}}close(CMD_LINE);}}# Check if PID foundmy $names;my $short_status;if ($vpn_found == 1) {$names = join('/', @config_name);$short_status='up';} else {$short_status='down';$names = $short_status;}print "$names\n";print "$short_status\n";# Print color if there were changesprint "#00FF00\n" if ($change == 1);exit(0);}sub check_opts {# Varsmy $pid_file_format=$ENV{PID_FILE_FORMAT} || '/run/openvpn/*.pid';# Set optionsGetOptions( "help|h" => \&help,"p=s" => \$pid_file_format);my @pid_file=glob $pid_file_format;print_output(\@pid_file);}sub help {print "Usage: openvpn [-p pid_file_format]\n";print "-p : format string to glob all pid files (default '/run/openvpn/*.pid)'\n";print "Note: devices in configuration file should be named with their number (ex: tun0, tap1)\n";exit(1);}&check_opts;
#!/usr/bin/env perl# Made by Pierre Mavro/Deimosfr <deimos@deimos.fr># Minor contribution by Thor K. H. <thor@roht.no># Licensed under the terms of the GNU GPL v3, or any later version.# Version: 0.3# Usage:# 1. The configuration name of OpenVPN should be familiar for you (home,work...)# 2. The device name in your configuration file should be fully named (tun0,tap1...not only tun or tap)# 3. When you launch one or multiple OpenVPN connexion, be sure the PID file is written in the correct folder (ex: --writepid /run/openvpn/home.pid)use strict;use warnings;use utf8;use Getopt::Long;my $openvpn_enabled='/dev/shm/openvpn_i3blocks_enabled';my $openvpn_disabled='/dev/shm/openvpn_i3blocks_disabled';# Print outputsub print_output {my $ref_pid_files = shift;my @pid_files = @$ref_pid_files;my $change=0;# Total pid filesmy $total_pid = @pid_files;if ($total_pid == 0) {print "down\n"x2;# Delete OpenVPN i3blocks temp filesif (-f $openvpn_enabled) {unlink $openvpn_enabled or die "Can't delete $openvpn_enabled\n";# Colorize if VPN has just went downprint '#FF0000\n';}unless (-f $openvpn_disabled) {open(my $shm, '>', $openvpn_disabled) or die "Can't write $openvpn_disabled\n";}exit(0);}# Check if interface device is presentmy $vpn_found=0;my $pid;my $cmd_line;my @config_name;my @config_path;my $interface;my $config_prefix;my $current_config_path;my $current_config_name;foreach (@pid_files) {# Get current PID$pid=0;open(PID, '<', $_);while(<PID>) {chomp $_;$pid = $_;}close(PID);# Check if PID has been foundif ($pid ==0) {print "Can't get PID $_: $!\n";}# Check if PID is still alive$cmd_line='/proc/'.$pid.'/cmdline';if (-f $cmd_line) {# Get config nameopen(CMD_LINE, '<', $cmd_line);while(<CMD_LINE>) {chomp $_;$config_prefix = "";if ($_ =~ /--cd\x{00}(.*?)\x{00}/) {$config_prefix = $1;}if ($_ =~ /--config\x{00}(.*?\.conf)\x{00}/) {# Get interface from config file$current_config_path = $1;# Remove unwanted escape chars$interface = 'null';# Get configuration nameif ($current_config_path =~ /(\w+).conf/) {$current_config_name=$1;} else {$current_config_name='unknown';}$current_config_path = "$config_prefix/$current_config_path";# Get OpenVPN interface device nameopen(CONFIG, '<', $current_config_path) or die "Can't read config file '$current_config_path': $!\n";while(<CONFIG>) {chomp $_;if ($_ =~ /dev\s+(\w+)/) {$interface=$1;last;}}close(CONFIG);# check if interface existunless ($interface eq 'null') {if (-d "/sys/class/net/$interface") {push @config_name, $current_config_name;$vpn_found=1;# Write enabled fileunless (-f $openvpn_enabled) {open(my $shm, '>', $openvpn_enabled) or die "Can't write $openvpn_enabled\n";$change=1;}}}}}close(CMD_LINE);}}# Check if PID foundmy $names;my $short_status;if ($vpn_found == 1) {$names = join('/', @config_name);$short_status='up';} else {$short_status='down';$names = $short_status;}print "$names\n";print "$short_status\n";# Print color if there were changesprint "#00FF00\n" if ($change == 1);exit(0);}sub check_opts {# Varsmy $pid_file_format=$ENV{PID_FILE_FORMAT} || '/run/openvpn/*.pid';# Set optionsGetOptions( "help|h" => \&help,"p=s" => \$pid_file_format);my @pid_file=glob $pid_file_format;print_output(\@pid_file);}sub help {print "Usage: openvpn [-p pid_file_format]\n";print "-p : format string to glob all pid files (default '/run/openvpn/*.pid)'\n";print "Note: devices in configuration file should be named with their number (ex: tun0, tap1)\n";exit(1);}&check_opts;
#!/usr/bin/env shinit_color=${init_color:-#FFFF00}on_color=${on_color:-#00FF00}export init_color on_colornmcli -t connection show --active | awk -F ':' 'BEGIN {init_color=ENVIRON["init_color"]on_color=ENVIRON["on_color"]}$3=="vpn" {name=$1status="INIT"color=init_color}$3=="tun" || ($4~/^tap/ || $3~/^tap/) {if(!name) name=$1status="ON"color=on_color}END {if(status) printf("%s\n%s\n%s\n", name, status, color)}'
#!/usr/bin/env shinit_color=${init_color:-#FFFF00}on_color=${on_color:-#00FF00}export init_color on_colornmcli -t connection show --active | awk -F ':' 'BEGIN {init_color=ENVIRON["init_color"]on_color=ENVIRON["on_color"]}$3=="vpn" {name=$1status="INIT"color=init_color}$3=="tun" || ($4~/^tap/ || $3~/^tap/) {if(!name) name=$1status="ON"color=on_color}END {if(status) printf("%s\n%s\n%s\n", name, status, color)}'
#!/usr/bin/env python3## Copyright (c) 2016 James Murphy# Licensed under the GPL version 2 only## monitor_manager is an i3blocks blocklet script to quickly manage your# connected output devicesfrom tkinter import *from tkinter import messageboxfrom shutil import whichimport tkinter.font as fontfrom subprocess import call, check_output, CalledProcessErrorimport reimport osDESKTOP_SYMBOL = "\uf108"UP_ARROW = "\uf062"DOWN_ARROW = "\uf063"UNBLANKED_SYMBOL = "\uf06e"BLANKED_SYMBOL = "\uf070"NOT_CLONED_SYMBOL = "\uf096"PRIMARY_SYMBOL = "\uf005"SECONDARY_SYMBOL = "\uf006"CLONED_SYMBOL = "\uf24d"ROTATION_NORMAL = "\uf151"ROTATION_LEFT = "\uf191"ROTATION_RIGHT = "\uf152"ROTATION_INVERTED = "\uf150"REFLECTION_NORMAL = "\uf176"REFLECTION_X = "\uf07e"REFLECTION_Y = "\uf07d"REFLECTION_XY = "\uf047"TOGGLE_ON = "\uf205"TOGGLE_OFF = "\uf204"APPLY_SYMBOL = "\uf00c"CANCEL_SYMBOL = "\uf00d"ARANDR_SYMBOL = "\uf085"REFRESH_SYMBOL = "\uf021"strbool = lambda s: s.lower() in ['t', 'true', '1']def _default(name, default='', arg_type=strbool):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)SHOW_ON_OFF = _default("SHOW_ON_OFF","1")SHOW_NAMES = _default("SHOW_NAMES", "1")SHOW_PRIMARY = _default("SHOW_PRIMARY", "1")SHOW_MODE = _default("SHOW_MODE", "1")SHOW_BLANKED = _default("SHOW_BLANKED", "1")SHOW_DUPLICATE = _default("SHOW_DUPLICATE", "1")SHOW_ROTATION = _default("SHOW_ROTATION", "1")SHOW_REFLECTION = _default("SHOW_REFLECTION", "1")SHOW_BRIGHTNESS = _default("SHOW_BRIGHTNESS", "1")SHOW_BRIGHTNESS_VALUE = _default("SHOW_BRIGHTNESS_VALUE", "0")SHOW_UP_DOWN = _default("SHOW_UP_DOWN", "1")FONTAWESOME_FONT_FAMILY = "FontAwesome"FONTAWESOME_FONT_SIZE = 11FONTAWESOME_FONT = (FONTAWESOME_FONT_FAMILY, FONTAWESOME_FONT_SIZE)DEFAULT_FONT_FAMILY = _default("FONT_FAMILY","DejaVu Sans Mono", str)DEFAULT_FONT_SIZE = _default("FONT_SIZE", 11, int)DEFAULT_FONT = (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE)BRIGHTNESS_SLIDER_HANDLE_LENGTH = 20BRIGHTNESS_SLIDER_WIDTH = 15BRIGHTNESS_SLIDER_LENGTH = 50WINDOW_CLOSE_TO_BOUNDARY_BUFFER = _default("CLOSE_TO_BOUNDARY_BUFFER", 20, int)class Output:def __init__(self, name=None, w=None, h=None, x=None, y=None, rate=None,active=False, primary=False, sameAs=None, blanked=False, rotation="normal",reflection="normal", brightness=1.0):self.name = nameself.w = wself.h = hself.x = xself.y = yself.rate = rateself.active = activeself.primary = primaryself.sameAs = sameAsself.blanked = blankedself.modes = []self.currentModeIndex = Noneself.preferredModeIndex = Noneself.row = Noneself.rotation = rotationself.reflection = reflectionself.brightness = brightnessdef setPreferredMode(self):if self.preferredModeIndex != None:self.setMode(self.preferredModeIndex)elif self.modes != None:self.setMode(0)def setMode(self, index):self.w, self.h, self.rate = self.modes[index]self.currentModeIndex = indexdef realOutputs():outputs = []xrandrText = check_output(["xrandr","--verbose"],universal_newlines=True)outputBlocks = re.split(r'\n(?=\S)', xrandrText, re.MULTILINE)infoPattern = re.compile(r'^(\S+)' # output name' connected ' # must be connected'(primary )?' # check if primary output'((\d+)x(\d+)\+(\d+)\+(\d+) )?' # width x height + xoffset + yoffset'(\(\S+\) )?' # mode code (0x4a)'(normal|left|inverted|right)? ?' # rotation'(X axis|Y axis|X and Y axis)?') # reflectionbrightnessPattern = re.compile(r'^\tBrightness: ([\d.]+)', re.MULTILINE)modePattern = re.compile(r'^ (\d+)x(\d+)[^\n]*?\n +h:[^\n]*?\n +v:[^\n]*?([\d.]+)Hz$', re.MULTILINE)for outputBlock in outputBlocks:output = Output()infoMatch = infoPattern.match(outputBlock)if infoMatch:output.name = infoMatch.group(1)if infoMatch.group(2):output.primary = Trueif infoMatch.group(3):output.active = Trueoutput.w, output.h, output.x, output.y = map(int,infoMatch.group(4, 5, 6, 7))if infoMatch.group(9):output.rotation = infoMatch.group(9)if output.rotation in ["left", "right"]:output.w, output.h = output.h, output.wif infoMatch.group(10):if infoMatch.group(10) == "X axis":output.reflection = "x"elif infoMatch.group(10) == "Y axis":output.reflection = "y"elif infoMatch.group(10) == "X and Y axis":output.reflection = "xy"else:output.reflection = "normal"else:output.reflection = "normal"brightnessMatch = brightnessPattern.search(outputBlock)if brightnessMatch:try:brightness = float(brightnessMatch.group(1))output.brightness = brightnessif abs(brightness) < 1e-09:output.blanked = Trueexcept ValueError:passmodeMatches = modePattern.finditer(outputBlock)for i, modeMatch in enumerate(modeMatches):if "*current" in modeMatch.group(0):output.currentModeIndex = ioutput.rate = modeMatch.group(3)if "+preferred" in modeMatch.group(0):output.preferredModeIndex = ioutput.modes.append(modeMatch.group(1,2,3))outputs.append(output)outputs.sort(key=lambda m: m.x if m.x != None else -1)prev = Nonefor output in outputs:if prev != None and output.active and prev.active and output.x == prev.x:output.sameAs = prev.nameelse:prev = outputreturn outputsdef modestr(mode):return "{}x{}@{}".format(*mode)def status(self):if self.active:if self.sameAs == None or self.sameAs == self.name:if self.w and self.h and self.rate:return "{}x{}@{}".format(self.w, self.h, self.rate)else:return "auto"else:return "duplicate {}".format(self.sameAs)else:return "Inactive"def __str__(self):return "{} {}x{}+{}+{} active:{}, primary:{}\nmodes:{}\ncurrentIndex:{} preferredIndex:{}".format(self.name, self.w, self.h, self.x, self.y, self.active, self.primary, self.modes, self.currentModeIndex, self.preferredModeIndex)class MonitorManager():def __init__(self, root):self.root = rootself.root.withdraw()self.root.resizable(0,0)self.root.wm_title("Monitor Manager")self.frame = Noneself.outputs = []self.hardRefreshList()style = {'relief':FLAT, 'padx':1, 'pady':1, 'anchor':'w', 'font':FONTAWESOME_FONT}self.infoLabel = Label(self.root, text="", **style)self.infoLabel.config(font=DEFAULT_FONT)self.bottomRow = []self.applyButton = Button(self.root, text=APPLY_SYMBOL, **style)self.bottomRow.append(self.applyButton)self.refreshButton = Button(self.root, text=REFRESH_SYMBOL, **style)self.bottomRow.append(self.refreshButton)if which("arandr"):self.arandrButton = Button(self.root, text=ARANDR_SYMBOL, **style)self.bottomRow.append(self.arandrButton)else:self.arandrButton = Noneself.cancelButton = Button(self.root, text=CANCEL_SYMBOL, **style)self.bottomRow.append(self.cancelButton)self.infoLabel.grid(row=1,column=0, columnspan=len(self.bottomRow))self.gridRow(2, self.bottomRow)self.moveToMouse()self.root.deiconify()def registerBindings(self):self.root.bind("<Return>", self.handleApply)self.root.bind("<Escape>", self.handleCancel)self.applyButton.bind("<Button-1>", self.handleApply)self.setInfo(self.applyButton, "Apply changes")self.refreshButton.bind("<Button-1>", self.hardRefreshList)self.setInfo(self.refreshButton, "Refresh list")if self.arandrButton:self.arandrButton.bind("<Button-1>", self.handleArandr)self.setInfo(self.arandrButton, "Launch aRandR")self.cancelButton.bind("<Button-1>", self.handleCancel)self.setInfo(self.cancelButton, "Cancel")for toggleButton in self.toggleButtons:toggleButton.bind("<Button-1>", self.toggleActive)toggleButton.bind("<Button-4>", self.handleUp)toggleButton.bind("<Button-5>", self.handleDown)self.setInfo(toggleButton, "Turn output on/off")for primaryButton in self.primaryButtons:primaryButton.bind("<Button-1>", self.setPrimary)self.setInfo(primaryButton, "Set primary output")for blankedButton in self.blankedButtons:blankedButton.bind("<Button-1>", self.toggleBlanked)self.setInfo(blankedButton, "Show/hide output")for duplicateButton in self.duplicateButtons:duplicateButton.bind("<Button-1>", self.toggleDuplicate)self.setInfo(duplicateButton, "Duplicate another output")for rotateButton in self.rotateButtons:rotateButton.bind("<Button-1>", self.cycleRotation)self.setInfo(rotateButton, "Rotate output")for reflectButton in self.reflectButtons:reflectButton.bind("<Button-1>", self.cycleReflection)self.setInfo(reflectButton, "Reflect output")for brightnessSlider in self.brightnessSliders:brightnessSlider.bind("<ButtonRelease-1>", self.updateBrightness)self.setInfo(brightnessSlider, "Adjust brightness")for upButton in self.upButtons:upButton.bind("<Button-1>", self.handleUp)upButton.bind("<Button-4>", self.handleUp)upButton.bind("<Button-5>", self.handleDown)self.setInfo(upButton, "Move up")for downButton in self.downButtons:downButton.bind("<Button-1>", self.handleDown)downButton.bind("<Button-4>", self.handleUp)downButton.bind("<Button-5>", self.handleDown)self.setInfo(downButton, "Move down")def gridRow(self, row, widgets):column = 0for w in widgets:w.grid(row=row, column=column)column += 1def moveToMouse(self):root = self.rootroot.update_idletasks()width = root.winfo_reqwidth()height = root.winfo_reqheight()x = root.winfo_pointerx() - width//2y = root.winfo_pointery() - height//2screen_width = root.winfo_screenwidth()screen_height = root.winfo_screenheight()if x+width > screen_width - WINDOW_CLOSE_TO_BOUNDARY_BUFFER:x = screen_width - WINDOW_CLOSE_TO_BOUNDARY_BUFFER - widthelif x < WINDOW_CLOSE_TO_BOUNDARY_BUFFER:x = WINDOW_CLOSE_TO_BOUNDARY_BUFFERif y+height > screen_height - WINDOW_CLOSE_TO_BOUNDARY_BUFFER:y = screen_height - WINDOW_CLOSE_TO_BOUNDARY_BUFFER - heightelif y < WINDOW_CLOSE_TO_BOUNDARY_BUFFER:y = WINDOW_CLOSE_TO_BOUNDARY_BUFFERroot.geometry('+{}+{}'.format(x, y))def setInfo(self, widget, info):widget.bind("<Enter>", lambda e: self.infoLabel.config(text=info, fg="black"))widget.bind("<Leave>", lambda e: self.infoLabel.config(text=""))def handleApply(self, e=None):self.root.after_idle(self.doHandleApply)def doHandleApply(self):if not self.getUserConfirmationIfDangerousConfiguration():returncommand = ["xrandr"]if not self.existsPrimary():command += ["--noprimary"]partition = self.sameAsPartition()prevFirstActive = Nonefor p in partition:firstActive = Nonefor output in p:command += ["--output", output.name]if output.active:if firstActive == None:firstActive = outputelse:command += ["--same-as", firstActive.name]if output.primary:command += ["--primary"]if prevFirstActive != None:command += ["--right-of", prevFirstActive.name]if output.w != None and output.h != None and output.rate != None:command += ["--mode", "{}x{}".format(output.w,output.h)]command += ["--rate", output.rate ]else:command += ["--auto"]command += ["--brightness", str(output.brightness)]command += ["--rotate", output.rotation]command += ["--reflect", output.reflection]else:command += ["--off"]if firstActive:prevFirstActive = firstActiveself.root.after_idle(lambda: self.executeXrandrCommand(command))def executeXrandrCommand(self, command):try:check_output(command, universal_newlines=True)except CalledProcessError as err:self.infoLabel.config(text="xrandr returned nonzero exit status {}".format(err.returncode), fg="red")def getUserConfirmationIfDangerousConfiguration(self):result = "yes"if all(map(lambda o: o.blanked or not o.active, self.outputs)):result = messagebox.askquestion("All blanked or off","All ouputs are set to be turned off or blanked, continue?",icon="warning")return result == "yes"def sameAsPartition(self):partition = []for output in self.outputs:place = Nonefor p in partition:if place != None:break;for o in p:if place == None and (output.sameAs == o.name or o.sameAs == output.name):place = pbreak;if place:place.append(output)else:partition.append([output])return partitiondef handleCancel(self, e=None):self.root.destroy()def handleArandr(self, e=None):call(["i3-msg", "-q", "exec", "arandr"])self.root.destroy()def handleUp(self, e):row = e.widget.output.rowif row > 0:self.swapOutputRows(row-1, row)self.softRefreshList()def handleDown(self, e):row = e.widget.output.rown = len(self.outputs)if row + 1 < n:self.swapOutputRows(row, row+1)self.softRefreshList()def swapOutputRows(self, row1, row2):outputs = self.outputsoutputs[row1],outputs[row2] = outputs[row2],outputs[row1]outputs[row1].row = row1outputs[row2].row = row2for widget in self.frame.grid_slaves(row=row2):widget.output = outputs[row2]for widget in self.frame.grid_slaves(row=row1):widget.output = outputs[row1]def setPrimary(self, e):output = e.widget.outputoutput.primary = not output.primaryfor otherOutput in self.outputs:if otherOutput != output:otherOutput.primary = Falseself.softRefreshList()def existsPrimary(self):for output in self.outputs:if output.primary:return Truereturn Falsedef toggleActive(self, e):output = e.widget.outputoutput.active = not output.activeif output.active:output.setPreferredMode()else:for otherOutput in self.outputs:if otherOutput.sameAs == output.name:otherOutput.sameAs = Noneself.softRefreshList()def toggleBlanked(self, e):output = e.widget.outputif output.blanked:output.blanked = Falseoutput.brightness = 1.0else:output.blanked = Trueoutput.brightness = 0.0self.softRefreshList()def updateBrightness(self, e):output = e.widget.outputoutput.brightness = .01 * e.widget.get()output.blanked = Falseif abs(output.brightness) < 1e-09:output.blanked = Trueself.softRefreshList()def cycleRotation(self, e):output = e.widget.outputif output.rotation == "normal":output.rotation = "right"elif output.rotation == "right":output.rotation = "inverted"elif output.rotation == "inverted":output.rotation = "left"else:output.rotation = "normal"self.softRefreshList()def rotationSymbol(self, rotation):return {"normal": ROTATION_NORMAL,"left": ROTATION_LEFT,"right": ROTATION_RIGHT,"inverted": ROTATION_INVERTED,}[rotation]def cycleReflection(self, e):output = e.widget.outputif output.reflection == "normal":output.reflection = "x"elif output.reflection == "x":output.reflection = "y"elif output.reflection == "y":output.reflection = "xy"else:output.reflection = "normal"self.softRefreshList()def reflectionSymbol(self, reflection):return {"normal": REFLECTION_NORMAL,"x": REFLECTION_X,"y": REFLECTION_Y,"xy": REFLECTION_XY,}[reflection]def toggleDuplicate(self, e):duplicateButton = e.widgetoptionMenu = duplicateButton.statusOptionMenuoutput = optionMenu.outputif output.sameAs != None:output.sameAs = Noneself.setMenuToOutput(optionMenu, output)else:self.setMenuToDuplicate(optionMenu)self.softRefreshList()def getDuplicableOutputsFor(self, output):return [o for o in self.outputs if o != output and o.sameAs == None]def softRefreshList(self, e=None):for widget in set().union(self.nameLabels, self.primaryButtons,self.statusOptionMenus, self.blankedButtons,self.duplicateButtons, self.rotateButtons, self.reflectButtons,self.brightnessSliders, self.upButtons, self.downButtons):widget.config(fg="gray" if not widget.output.active else "black")for widget in self.toggleButtons:widget.config(text=TOGGLE_ON if widget.output.active else TOGGLE_OFF)for widget in self.nameLabels:widget.config(text=widget.output.name)for widget in self.primaryButtons:widget.config(text=PRIMARY_SYMBOL if widget.output.primary else SECONDARY_SYMBOL)if not widget.output.primary:widget.config(fg="gray")for widget in self.statusOptionMenus:widget.config(text=widget.output.status())if widget.output.sameAs != None:self.setMenuToDuplicate(widget)self.setInfo(widget, "Select output to duplicate")else:self.setMenuToOutput(widget, widget.output)self.setInfo(widget, "Select output mode")for widget in self.blankedButtons:widget.config(text=BLANKED_SYMBOL if widget.output.blanked else UNBLANKED_SYMBOL)for widget in self.duplicateButtons:widget.config(text=CLONED_SYMBOL if widget.output.sameAs else NOT_CLONED_SYMBOL)for widget in self.rotateButtons:widget.config(text=self.rotationSymbol(widget.output.rotation))for widget in self.reflectButtons:widget.config(text=self.reflectionSymbol(widget.output.reflection))for widget in self.brightnessSliders:widget.set(int(100*widget.output.brightness))def hardRefreshList(self, e=None):self.outputs = Output.realOutputs()self.root.after_idle(self.populateGrid)def populateGrid(self):oldFrame = self.frameself.frame = Frame(self.root)self.frame.grid(row=0, column=0, columnspan=len(self.bottomRow))self.toggleButtons = []self.nameLabels = []self.primaryButtons = []self.statusOptionMenus = []self.blankedButtons = []self.duplicateButtons = []self.rotateButtons = []self.reflectButtons = []self.brightnessSliders = []self.upButtons = []self.downButtons = []for row, output in enumerate(self.outputs):self.makeLabelRow(output, row)self.registerBindings()if oldFrame:oldFrame.destroy()def makeLabelRow(self, output, row):output.row = rowstyle = {'relief':FLAT, 'padx':1, 'pady':1, 'anchor':'w'}widgets = []toggleButton = Button(self.frame, font=FONTAWESOME_FONT, **style)toggleButton.output = outputself.toggleButtons.append(toggleButton)if SHOW_ON_OFF:widgets.append(toggleButton)nameLabel = Label(self.frame, font=DEFAULT_FONT)nameLabel.output = outputself.nameLabels.append(nameLabel)if SHOW_NAMES:widgets.append(nameLabel)primaryButton = Button(self.frame, font=FONTAWESOME_FONT, **style)primaryButton.output = outputself.primaryButtons.append(primaryButton)if not output.primary:primaryButton.config(fg="gray")if SHOW_PRIMARY:widgets.append(primaryButton)var = StringVar(self.frame)statusOptionMenu = OptionMenu(self.frame, var, None)statusOptionMenu.output = outputstatusOptionMenu.var = varstatusOptionMenu.config(relief=FLAT)self.statusOptionMenus.append(statusOptionMenu)if SHOW_MODE or SHOW_DUPLICATE:widgets.append(statusOptionMenu)blankedButton = Button(self.frame, font=FONTAWESOME_FONT, **style)blankedButton.output = outputself.blankedButtons.append(blankedButton)if SHOW_BLANKED:widgets.append(blankedButton)duplicateButton = Button(self.frame, font=FONTAWESOME_FONT, **style)duplicateButton.statusOptionMenu = statusOptionMenuduplicateButton.output = outputself.duplicateButtons.append(duplicateButton)if SHOW_DUPLICATE:widgets.append(duplicateButton)rotateButton = Button(self.frame, font=FONTAWESOME_FONT, **style)rotateButton.output = outputself.rotateButtons.append(rotateButton)if SHOW_ROTATION:widgets.append(rotateButton)reflectButton = Button(self.frame, font=FONTAWESOME_FONT, **style)reflectButton.output = outputself.reflectButtons.append(reflectButton)if SHOW_REFLECTION:widgets.append(reflectButton)brightnessSlider = Scale(self.frame, orient="horizontal", from_=0, to=100,length=BRIGHTNESS_SLIDER_LENGTH, showvalue=SHOW_BRIGHTNESS_VALUE,sliderlength=BRIGHTNESS_SLIDER_HANDLE_LENGTH,width=BRIGHTNESS_SLIDER_WIDTH, font=FONTAWESOME_FONT)brightnessSlider.output = outputself.brightnessSliders.append(brightnessSlider)if SHOW_BRIGHTNESS:widgets.append(brightnessSlider)upButton = Button(self.frame, text=UP_ARROW, font=FONTAWESOME_FONT, **style)upButton.output = outputself.upButtons.append(upButton)if SHOW_UP_DOWN:widgets.append(upButton)downButton = Button(self.frame, text=DOWN_ARROW, font=FONTAWESOME_FONT, **style)downButton.output = outputself.downButtons.append(downButton)if SHOW_UP_DOWN:widgets.append(downButton)for widget in widgets:widget.output = outputself.gridRow(row, widgets)self.softRefreshList()def setMenuToOutput(self, optionMenu, output):menu = optionMenu["menu"]var = optionMenu.varmodes = output.modesmenu.delete(0, END)for i, mode in enumerate(modes):label = Output.modestr(mode)menu.add_command(label=label, command=setLabelAndOutputModeFunc(var,label,output,i))if output.currentModeIndex != None:var.set(Output.modestr(modes[output.currentModeIndex]))elif output.preferredModeIndex != None:var.set(Output.modestr(modes[output.preferredModeIndex]))elif len(modes) > 0:var.set(Output.modestr(modes[0]))def setMenuToDuplicate(self, optionMenu):menu = optionMenu["menu"]var = optionMenu.varoutput = optionMenu.outputmenu.delete(0, END)duplicables = self.getDuplicableOutputsFor(output)defaultIndex = 0for i,otherOutput in enumerate(duplicables):label = otherOutput.namemenu.add_command(label=label, command=setLabelAndSameAsFunc(var,label,output))if label == output.sameAs:defaultIndex = iif len(duplicables) > 0:var.set(menu.entrycget(defaultIndex, "label"))output.sameAs = menu.entrycget(defaultIndex, "label")else:var.set("None")def handleFocusOut(self, event):self.root.destroy()def setLabelAndOutputModeFunc(var, label, output, i):def func():var.set(label)output.setMode(i)return funcdef setLabelAndSameAsFunc(var, sameAs, output):def func():var.set(sameAs)output.sameAs = sameAsreturn funcif os.environ.get('BLOCK_BUTTON') == "1":if os.fork() != 0:root = Tk()if DEFAULT_FONT_FAMILY and DEFAULT_FONT_SIZE:font.nametofont("TkDefaultFont").config(family=DEFAULT_FONT_FAMILY, size=DEFAULT_FONT_SIZE)manager = MonitorManager(root)root.mainloop()else:print(DESKTOP_SYMBOL)else:print(DESKTOP_SYMBOL)
#!/usr/bin/env python3## Copyright (c) 2016 James Murphy# Licensed under the GPL version 2 only## monitor_manager is an i3blocks blocklet script to quickly manage your# connected output devicesfrom tkinter import *from tkinter import messageboxfrom shutil import whichimport tkinter.font as fontfrom subprocess import call, check_output, CalledProcessErrorimport reimport osDESKTOP_SYMBOL = "\uf108"UP_ARROW = "\uf062"DOWN_ARROW = "\uf063"UNBLANKED_SYMBOL = "\uf06e"BLANKED_SYMBOL = "\uf070"NOT_CLONED_SYMBOL = "\uf096"PRIMARY_SYMBOL = "\uf005"SECONDARY_SYMBOL = "\uf006"CLONED_SYMBOL = "\uf24d"ROTATION_NORMAL = "\uf151"ROTATION_LEFT = "\uf191"ROTATION_RIGHT = "\uf152"ROTATION_INVERTED = "\uf150"REFLECTION_NORMAL = "\uf176"REFLECTION_X = "\uf07e"REFLECTION_Y = "\uf07d"REFLECTION_XY = "\uf047"TOGGLE_ON = "\uf205"TOGGLE_OFF = "\uf204"APPLY_SYMBOL = "\uf00c"CANCEL_SYMBOL = "\uf00d"ARANDR_SYMBOL = "\uf085"REFRESH_SYMBOL = "\uf021"strbool = lambda s: s.lower() in ['t', 'true', '1']def _default(name, default='', arg_type=strbool):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)SHOW_ON_OFF = _default("SHOW_ON_OFF","1")SHOW_NAMES = _default("SHOW_NAMES", "1")SHOW_PRIMARY = _default("SHOW_PRIMARY", "1")SHOW_MODE = _default("SHOW_MODE", "1")SHOW_BLANKED = _default("SHOW_BLANKED", "1")SHOW_DUPLICATE = _default("SHOW_DUPLICATE", "1")SHOW_ROTATION = _default("SHOW_ROTATION", "1")SHOW_REFLECTION = _default("SHOW_REFLECTION", "1")SHOW_BRIGHTNESS = _default("SHOW_BRIGHTNESS", "1")SHOW_BRIGHTNESS_VALUE = _default("SHOW_BRIGHTNESS_VALUE", "0")SHOW_UP_DOWN = _default("SHOW_UP_DOWN", "1")FONTAWESOME_FONT_FAMILY = "FontAwesome"FONTAWESOME_FONT_SIZE = 11FONTAWESOME_FONT = (FONTAWESOME_FONT_FAMILY, FONTAWESOME_FONT_SIZE)DEFAULT_FONT_FAMILY = _default("FONT_FAMILY","DejaVu Sans Mono", str)DEFAULT_FONT_SIZE = _default("FONT_SIZE", 11, int)DEFAULT_FONT = (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE)BRIGHTNESS_SLIDER_HANDLE_LENGTH = 20BRIGHTNESS_SLIDER_WIDTH = 15BRIGHTNESS_SLIDER_LENGTH = 50WINDOW_CLOSE_TO_BOUNDARY_BUFFER = _default("CLOSE_TO_BOUNDARY_BUFFER", 20, int)class Output:def __init__(self, name=None, w=None, h=None, x=None, y=None, rate=None,active=False, primary=False, sameAs=None, blanked=False, rotation="normal",reflection="normal", brightness=1.0):self.name = nameself.w = wself.h = hself.x = xself.y = yself.rate = rateself.active = activeself.primary = primaryself.sameAs = sameAsself.blanked = blankedself.modes = []self.currentModeIndex = Noneself.preferredModeIndex = Noneself.row = Noneself.rotation = rotationself.reflection = reflectionself.brightness = brightnessdef setPreferredMode(self):if self.preferredModeIndex != None:self.setMode(self.preferredModeIndex)elif self.modes != None:self.setMode(0)def setMode(self, index):self.w, self.h, self.rate = self.modes[index]self.currentModeIndex = indexdef realOutputs():outputs = []xrandrText = check_output(["xrandr","--verbose"],universal_newlines=True)outputBlocks = re.split(r'\n(?=\S)', xrandrText, re.MULTILINE)infoPattern = re.compile(r'^(\S+)' # output name' connected ' # must be connected'(primary )?' # check if primary output'((\d+)x(\d+)\+(\d+)\+(\d+) )?' # width x height + xoffset + yoffset'(\(\S+\) )?' # mode code (0x4a)'(normal|left|inverted|right)? ?' # rotation'(X axis|Y axis|X and Y axis)?') # reflectionbrightnessPattern = re.compile(r'^\tBrightness: ([\d.]+)', re.MULTILINE)modePattern = re.compile(r'^ (\d+)x(\d+)[^\n]*?\n +h:[^\n]*?\n +v:[^\n]*?([\d.]+)Hz$', re.MULTILINE)for outputBlock in outputBlocks:output = Output()infoMatch = infoPattern.match(outputBlock)if infoMatch:output.name = infoMatch.group(1)if infoMatch.group(2):output.primary = Trueif infoMatch.group(3):output.active = Trueoutput.w, output.h, output.x, output.y = map(int,infoMatch.group(4, 5, 6, 7))if infoMatch.group(9):output.rotation = infoMatch.group(9)if output.rotation in ["left", "right"]:output.w, output.h = output.h, output.wif infoMatch.group(10):if infoMatch.group(10) == "X axis":output.reflection = "x"elif infoMatch.group(10) == "Y axis":output.reflection = "y"elif infoMatch.group(10) == "X and Y axis":output.reflection = "xy"else:output.reflection = "normal"else:output.reflection = "normal"brightnessMatch = brightnessPattern.search(outputBlock)if brightnessMatch:try:brightness = float(brightnessMatch.group(1))output.brightness = brightnessif abs(brightness) < 1e-09:output.blanked = Trueexcept ValueError:passmodeMatches = modePattern.finditer(outputBlock)for i, modeMatch in enumerate(modeMatches):if "*current" in modeMatch.group(0):output.currentModeIndex = ioutput.rate = modeMatch.group(3)if "+preferred" in modeMatch.group(0):output.preferredModeIndex = ioutput.modes.append(modeMatch.group(1,2,3))outputs.append(output)outputs.sort(key=lambda m: m.x if m.x != None else -1)prev = Nonefor output in outputs:if prev != None and output.active and prev.active and output.x == prev.x:output.sameAs = prev.nameelse:prev = outputreturn outputsdef modestr(mode):return "{}x{}@{}".format(*mode)def status(self):if self.active:if self.sameAs == None or self.sameAs == self.name:if self.w and self.h and self.rate:return "{}x{}@{}".format(self.w, self.h, self.rate)else:return "auto"else:return "duplicate {}".format(self.sameAs)else:return "Inactive"def __str__(self):return "{} {}x{}+{}+{} active:{}, primary:{}\nmodes:{}\ncurrentIndex:{} preferredIndex:{}".format(self.name, self.w, self.h, self.x, self.y, self.active, self.primary, self.modes, self.currentModeIndex, self.preferredModeIndex)class MonitorManager():def __init__(self, root):self.root = rootself.root.withdraw()self.root.resizable(0,0)self.root.wm_title("Monitor Manager")self.frame = Noneself.outputs = []self.hardRefreshList()style = {'relief':FLAT, 'padx':1, 'pady':1, 'anchor':'w', 'font':FONTAWESOME_FONT}self.infoLabel = Label(self.root, text="", **style)self.infoLabel.config(font=DEFAULT_FONT)self.bottomRow = []self.applyButton = Button(self.root, text=APPLY_SYMBOL, **style)self.bottomRow.append(self.applyButton)self.refreshButton = Button(self.root, text=REFRESH_SYMBOL, **style)self.bottomRow.append(self.refreshButton)if which("arandr"):self.arandrButton = Button(self.root, text=ARANDR_SYMBOL, **style)self.bottomRow.append(self.arandrButton)else:self.arandrButton = Noneself.cancelButton = Button(self.root, text=CANCEL_SYMBOL, **style)self.bottomRow.append(self.cancelButton)self.infoLabel.grid(row=1,column=0, columnspan=len(self.bottomRow))self.gridRow(2, self.bottomRow)self.moveToMouse()self.root.deiconify()def registerBindings(self):self.root.bind("<Return>", self.handleApply)self.root.bind("<Escape>", self.handleCancel)self.applyButton.bind("<Button-1>", self.handleApply)self.setInfo(self.applyButton, "Apply changes")self.refreshButton.bind("<Button-1>", self.hardRefreshList)self.setInfo(self.refreshButton, "Refresh list")if self.arandrButton:self.arandrButton.bind("<Button-1>", self.handleArandr)self.setInfo(self.arandrButton, "Launch aRandR")self.cancelButton.bind("<Button-1>", self.handleCancel)self.setInfo(self.cancelButton, "Cancel")for toggleButton in self.toggleButtons:toggleButton.bind("<Button-1>", self.toggleActive)toggleButton.bind("<Button-4>", self.handleUp)toggleButton.bind("<Button-5>", self.handleDown)self.setInfo(toggleButton, "Turn output on/off")for primaryButton in self.primaryButtons:primaryButton.bind("<Button-1>", self.setPrimary)self.setInfo(primaryButton, "Set primary output")for blankedButton in self.blankedButtons:blankedButton.bind("<Button-1>", self.toggleBlanked)self.setInfo(blankedButton, "Show/hide output")for duplicateButton in self.duplicateButtons:duplicateButton.bind("<Button-1>", self.toggleDuplicate)self.setInfo(duplicateButton, "Duplicate another output")for rotateButton in self.rotateButtons:rotateButton.bind("<Button-1>", self.cycleRotation)self.setInfo(rotateButton, "Rotate output")for reflectButton in self.reflectButtons:reflectButton.bind("<Button-1>", self.cycleReflection)self.setInfo(reflectButton, "Reflect output")for brightnessSlider in self.brightnessSliders:brightnessSlider.bind("<ButtonRelease-1>", self.updateBrightness)self.setInfo(brightnessSlider, "Adjust brightness")for upButton in self.upButtons:upButton.bind("<Button-1>", self.handleUp)upButton.bind("<Button-4>", self.handleUp)upButton.bind("<Button-5>", self.handleDown)self.setInfo(upButton, "Move up")for downButton in self.downButtons:downButton.bind("<Button-1>", self.handleDown)downButton.bind("<Button-4>", self.handleUp)downButton.bind("<Button-5>", self.handleDown)self.setInfo(downButton, "Move down")def gridRow(self, row, widgets):column = 0for w in widgets:w.grid(row=row, column=column)column += 1def moveToMouse(self):root = self.rootroot.update_idletasks()width = root.winfo_reqwidth()height = root.winfo_reqheight()x = root.winfo_pointerx() - width//2y = root.winfo_pointery() - height//2screen_width = root.winfo_screenwidth()screen_height = root.winfo_screenheight()if x+width > screen_width - WINDOW_CLOSE_TO_BOUNDARY_BUFFER:x = screen_width - WINDOW_CLOSE_TO_BOUNDARY_BUFFER - widthelif x < WINDOW_CLOSE_TO_BOUNDARY_BUFFER:x = WINDOW_CLOSE_TO_BOUNDARY_BUFFERif y+height > screen_height - WINDOW_CLOSE_TO_BOUNDARY_BUFFER:y = screen_height - WINDOW_CLOSE_TO_BOUNDARY_BUFFER - heightelif y < WINDOW_CLOSE_TO_BOUNDARY_BUFFER:y = WINDOW_CLOSE_TO_BOUNDARY_BUFFERroot.geometry('+{}+{}'.format(x, y))def setInfo(self, widget, info):widget.bind("<Enter>", lambda e: self.infoLabel.config(text=info, fg="black"))widget.bind("<Leave>", lambda e: self.infoLabel.config(text=""))def handleApply(self, e=None):self.root.after_idle(self.doHandleApply)def doHandleApply(self):if not self.getUserConfirmationIfDangerousConfiguration():returncommand = ["xrandr"]if not self.existsPrimary():command += ["--noprimary"]partition = self.sameAsPartition()prevFirstActive = Nonefor p in partition:firstActive = Nonefor output in p:command += ["--output", output.name]if output.active:if firstActive == None:firstActive = outputelse:command += ["--same-as", firstActive.name]if output.primary:command += ["--primary"]if prevFirstActive != None:command += ["--right-of", prevFirstActive.name]if output.w != None and output.h != None and output.rate != None:command += ["--mode", "{}x{}".format(output.w,output.h)]command += ["--rate", output.rate ]else:command += ["--auto"]command += ["--brightness", str(output.brightness)]command += ["--rotate", output.rotation]command += ["--reflect", output.reflection]else:command += ["--off"]if firstActive:prevFirstActive = firstActiveself.root.after_idle(lambda: self.executeXrandrCommand(command))def executeXrandrCommand(self, command):try:check_output(command, universal_newlines=True)except CalledProcessError as err:self.infoLabel.config(text="xrandr returned nonzero exit status {}".format(err.returncode), fg="red")def getUserConfirmationIfDangerousConfiguration(self):result = "yes"if all(map(lambda o: o.blanked or not o.active, self.outputs)):result = messagebox.askquestion("All blanked or off","All ouputs are set to be turned off or blanked, continue?",icon="warning")return result == "yes"def sameAsPartition(self):partition = []for output in self.outputs:place = Nonefor p in partition:if place != None:break;for o in p:if place == None and (output.sameAs == o.name or o.sameAs == output.name):place = pbreak;if place:place.append(output)else:partition.append([output])return partitiondef handleCancel(self, e=None):self.root.destroy()def handleArandr(self, e=None):call(["i3-msg", "-q", "exec", "arandr"])self.root.destroy()def handleUp(self, e):row = e.widget.output.rowif row > 0:self.swapOutputRows(row-1, row)self.softRefreshList()def handleDown(self, e):row = e.widget.output.rown = len(self.outputs)if row + 1 < n:self.swapOutputRows(row, row+1)self.softRefreshList()def swapOutputRows(self, row1, row2):outputs = self.outputsoutputs[row1],outputs[row2] = outputs[row2],outputs[row1]outputs[row1].row = row1outputs[row2].row = row2for widget in self.frame.grid_slaves(row=row2):widget.output = outputs[row2]for widget in self.frame.grid_slaves(row=row1):widget.output = outputs[row1]def setPrimary(self, e):output = e.widget.outputoutput.primary = not output.primaryfor otherOutput in self.outputs:if otherOutput != output:otherOutput.primary = Falseself.softRefreshList()def existsPrimary(self):for output in self.outputs:if output.primary:return Truereturn Falsedef toggleActive(self, e):output = e.widget.outputoutput.active = not output.activeif output.active:output.setPreferredMode()else:for otherOutput in self.outputs:if otherOutput.sameAs == output.name:otherOutput.sameAs = Noneself.softRefreshList()def toggleBlanked(self, e):output = e.widget.outputif output.blanked:output.blanked = Falseoutput.brightness = 1.0else:output.blanked = Trueoutput.brightness = 0.0self.softRefreshList()def updateBrightness(self, e):output = e.widget.outputoutput.brightness = .01 * e.widget.get()output.blanked = Falseif abs(output.brightness) < 1e-09:output.blanked = Trueself.softRefreshList()def cycleRotation(self, e):output = e.widget.outputif output.rotation == "normal":output.rotation = "right"elif output.rotation == "right":output.rotation = "inverted"elif output.rotation == "inverted":output.rotation = "left"else:output.rotation = "normal"self.softRefreshList()def rotationSymbol(self, rotation):return {"normal": ROTATION_NORMAL,"left": ROTATION_LEFT,"right": ROTATION_RIGHT,"inverted": ROTATION_INVERTED,}[rotation]def cycleReflection(self, e):output = e.widget.outputif output.reflection == "normal":output.reflection = "x"elif output.reflection == "x":output.reflection = "y"elif output.reflection == "y":output.reflection = "xy"else:output.reflection = "normal"self.softRefreshList()def reflectionSymbol(self, reflection):return {"normal": REFLECTION_NORMAL,"x": REFLECTION_X,"y": REFLECTION_Y,"xy": REFLECTION_XY,}[reflection]def toggleDuplicate(self, e):duplicateButton = e.widgetoptionMenu = duplicateButton.statusOptionMenuoutput = optionMenu.outputif output.sameAs != None:output.sameAs = Noneself.setMenuToOutput(optionMenu, output)else:self.setMenuToDuplicate(optionMenu)self.softRefreshList()def getDuplicableOutputsFor(self, output):return [o for o in self.outputs if o != output and o.sameAs == None]def softRefreshList(self, e=None):for widget in set().union(self.nameLabels, self.primaryButtons,self.statusOptionMenus, self.blankedButtons,self.duplicateButtons, self.rotateButtons, self.reflectButtons,self.brightnessSliders, self.upButtons, self.downButtons):widget.config(fg="gray" if not widget.output.active else "black")for widget in self.toggleButtons:widget.config(text=TOGGLE_ON if widget.output.active else TOGGLE_OFF)for widget in self.nameLabels:widget.config(text=widget.output.name)for widget in self.primaryButtons:widget.config(text=PRIMARY_SYMBOL if widget.output.primary else SECONDARY_SYMBOL)if not widget.output.primary:widget.config(fg="gray")for widget in self.statusOptionMenus:widget.config(text=widget.output.status())if widget.output.sameAs != None:self.setMenuToDuplicate(widget)self.setInfo(widget, "Select output to duplicate")else:self.setMenuToOutput(widget, widget.output)self.setInfo(widget, "Select output mode")for widget in self.blankedButtons:widget.config(text=BLANKED_SYMBOL if widget.output.blanked else UNBLANKED_SYMBOL)for widget in self.duplicateButtons:widget.config(text=CLONED_SYMBOL if widget.output.sameAs else NOT_CLONED_SYMBOL)for widget in self.rotateButtons:widget.config(text=self.rotationSymbol(widget.output.rotation))for widget in self.reflectButtons:widget.config(text=self.reflectionSymbol(widget.output.reflection))for widget in self.brightnessSliders:widget.set(int(100*widget.output.brightness))def hardRefreshList(self, e=None):self.outputs = Output.realOutputs()self.root.after_idle(self.populateGrid)def populateGrid(self):oldFrame = self.frameself.frame = Frame(self.root)self.frame.grid(row=0, column=0, columnspan=len(self.bottomRow))self.toggleButtons = []self.nameLabels = []self.primaryButtons = []self.statusOptionMenus = []self.blankedButtons = []self.duplicateButtons = []self.rotateButtons = []self.reflectButtons = []self.brightnessSliders = []self.upButtons = []self.downButtons = []for row, output in enumerate(self.outputs):self.makeLabelRow(output, row)self.registerBindings()if oldFrame:oldFrame.destroy()def makeLabelRow(self, output, row):output.row = rowstyle = {'relief':FLAT, 'padx':1, 'pady':1, 'anchor':'w'}widgets = []toggleButton = Button(self.frame, font=FONTAWESOME_FONT, **style)toggleButton.output = outputself.toggleButtons.append(toggleButton)if SHOW_ON_OFF:widgets.append(toggleButton)nameLabel = Label(self.frame, font=DEFAULT_FONT)nameLabel.output = outputself.nameLabels.append(nameLabel)if SHOW_NAMES:widgets.append(nameLabel)primaryButton = Button(self.frame, font=FONTAWESOME_FONT, **style)primaryButton.output = outputself.primaryButtons.append(primaryButton)if not output.primary:primaryButton.config(fg="gray")if SHOW_PRIMARY:widgets.append(primaryButton)var = StringVar(self.frame)statusOptionMenu = OptionMenu(self.frame, var, None)statusOptionMenu.output = outputstatusOptionMenu.var = varstatusOptionMenu.config(relief=FLAT)self.statusOptionMenus.append(statusOptionMenu)if SHOW_MODE or SHOW_DUPLICATE:widgets.append(statusOptionMenu)blankedButton = Button(self.frame, font=FONTAWESOME_FONT, **style)blankedButton.output = outputself.blankedButtons.append(blankedButton)if SHOW_BLANKED:widgets.append(blankedButton)duplicateButton = Button(self.frame, font=FONTAWESOME_FONT, **style)duplicateButton.statusOptionMenu = statusOptionMenuduplicateButton.output = outputself.duplicateButtons.append(duplicateButton)if SHOW_DUPLICATE:widgets.append(duplicateButton)rotateButton = Button(self.frame, font=FONTAWESOME_FONT, **style)rotateButton.output = outputself.rotateButtons.append(rotateButton)if SHOW_ROTATION:widgets.append(rotateButton)reflectButton = Button(self.frame, font=FONTAWESOME_FONT, **style)reflectButton.output = outputself.reflectButtons.append(reflectButton)if SHOW_REFLECTION:widgets.append(reflectButton)brightnessSlider = Scale(self.frame, orient="horizontal", from_=0, to=100,length=BRIGHTNESS_SLIDER_LENGTH, showvalue=SHOW_BRIGHTNESS_VALUE,sliderlength=BRIGHTNESS_SLIDER_HANDLE_LENGTH,width=BRIGHTNESS_SLIDER_WIDTH, font=FONTAWESOME_FONT)brightnessSlider.output = outputself.brightnessSliders.append(brightnessSlider)if SHOW_BRIGHTNESS:widgets.append(brightnessSlider)upButton = Button(self.frame, text=UP_ARROW, font=FONTAWESOME_FONT, **style)upButton.output = outputself.upButtons.append(upButton)if SHOW_UP_DOWN:widgets.append(upButton)downButton = Button(self.frame, text=DOWN_ARROW, font=FONTAWESOME_FONT, **style)downButton.output = outputself.downButtons.append(downButton)if SHOW_UP_DOWN:widgets.append(downButton)for widget in widgets:widget.output = outputself.gridRow(row, widgets)self.softRefreshList()def setMenuToOutput(self, optionMenu, output):menu = optionMenu["menu"]var = optionMenu.varmodes = output.modesmenu.delete(0, END)for i, mode in enumerate(modes):label = Output.modestr(mode)menu.add_command(label=label, command=setLabelAndOutputModeFunc(var,label,output,i))if output.currentModeIndex != None:var.set(Output.modestr(modes[output.currentModeIndex]))elif output.preferredModeIndex != None:var.set(Output.modestr(modes[output.preferredModeIndex]))elif len(modes) > 0:var.set(Output.modestr(modes[0]))def setMenuToDuplicate(self, optionMenu):menu = optionMenu["menu"]var = optionMenu.varoutput = optionMenu.outputmenu.delete(0, END)duplicables = self.getDuplicableOutputsFor(output)defaultIndex = 0for i,otherOutput in enumerate(duplicables):label = otherOutput.namemenu.add_command(label=label, command=setLabelAndSameAsFunc(var,label,output))if label == output.sameAs:defaultIndex = iif len(duplicables) > 0:var.set(menu.entrycget(defaultIndex, "label"))output.sameAs = menu.entrycget(defaultIndex, "label")else:var.set("None")def handleFocusOut(self, event):self.root.destroy()def setLabelAndOutputModeFunc(var, label, output, i):def func():var.set(label)output.setMode(i)return funcdef setLabelAndSameAsFunc(var, sameAs, output):def func():var.set(sameAs)output.sameAs = sameAsreturn funcif os.environ.get('BLOCK_BUTTON') == "1":if os.fork() != 0:root = Tk()if DEFAULT_FONT_FAMILY and DEFAULT_FONT_SIZE:font.nametofont("TkDefaultFont").config(family=DEFAULT_FONT_FAMILY, size=DEFAULT_FONT_SIZE)manager = MonitorManager(root)root.mainloop()else:print(DESKTOP_SYMBOL)else:print(DESKTOP_SYMBOL)
#!/bin/bash## Copyright © 2020 Filip Paskali## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.case $BLOCK_BUTTON in1|3) pactl set-source-mute $SOURCE toggle ;;esaccase $(pacmd list-sources | grep -A 11 "$SOURCE" | awk '/muted/ {print $2; exit}') inyes)echo "";;no)echo "";;esac
#!/bin/bash## Copyright © 2020 Filip Paskali## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.case $BLOCK_BUTTON in1|3) pactl set-source-mute $SOURCE toggle ;;esaccase $(pacmd list-sources | grep -A 11 "$SOURCE" | awk '/muted/ {print $2; exit}') inyes)echo "";;no)echo "";;esac
#!/usr/bin/env python3# Required steps before running this scripts:# > sudo pip install python-metar# > sudo pacman -S libnotify# Possibly also:# > sudo pacman -S dunstimport osimport sys# Let's use json here for performance reasons:# https://stackoverflow.com/questions/988228/convert-a-string-representation-of-a-dictionary-to-a-dictionaryimport jsonimport datetimeimport subprocessimport urllib.requestfrom metar import Metarclass MetarsSettingsEnvironment:def isConfigured(self):# return Trueif not 'METARSSTATION' in os.environ:return Falseif not 'METARSURL' in os.environ:return Falseif not 'METARSENABLEMENTS' in os.environ:return Falseif not 'METARSCONFIGS' in os.environ:return Falsereturn Truedef extractAndUnpack(self, settings):try:extracted = json.loads(settings)except Exception as e:print('METARS extract 1: {}'.format(e))sys.exit(1)for k, v in extracted.items():try:setattr(self, k, v)except Exception as e:print('METARS extract 2: {}'.format(e))sys.exit(1)def extract(self):self.station = os.environ['METARSSTATION']self.metarurl = os.environ['METARSURL']enablements = os.environ['METARSENABLEMENTS']configs = os.environ['METARSCONFIGS']# self.station = 'EFHK'# self.metarurl = 'https://tgftp.nws.noaa.gov/data/observations/metar/stations/{}.TXT'# enablements = '{ "temperature": true, "dewpoint" : false, "feelsLike" : true, "wind" : true, "pressure" : false, "visibility" : false, "windDirType" : "icon", "useInverseWind" : false }'# configs = '{ "temperatureUnit" : "C", "temperatureSym" : "°C", "pressureUnit" : "HPA", "pressureSym" : "hPa", "speedUnit" : "MPS", "speedSym" : "m/s", "distanceUnit" : "KM", "distanceSym" : "km", "precipitationUnit" : "CM", "precipitationSym" : "cm"}'self.extractAndUnpack(enablements)self.extractAndUnpack(configs)class Metars:obs = {}settings = Nonemetarurl = 'https://tgftp.nws.noaa.gov/data/observations/metar/stations/{}.TXT'def __init__(self, settings):self.settings = settingsdef runCommand(self, command):retCode = 0retText = ''try:retText = subprocess.check_output(command, shell=True).decode('UTF-8')except subprocess.CalledProcessError as e:retCode = e.returncoderetText = e.output.decode('UTF-8')except:retCode = -999retText = 'ERROR: Unknown exception.'return retCode, retTextdef getChillMetric(self, temp, velocity): # temp = C, velocity = km/hif temp > 10.0 or velocity <= 4.8:return Noneexpt = velocity ** 0.16twc = 13.12 + (0.6215 * temp) - (11.37 * expt) + (0.3965 * temp * expt)return twcdef convertCelciusTo(self, temp):if self.settings.temperatureUnit == 'C':return tempelif self.settings.temperatureUnit == 'F':return (temp * 1.8) + 32elif self.settings.temperatureUnit == 'K':return temp + 273.15print('METARS: Unknown unit "{}"'.format(self.settings.temperatureUnit))sys.exit(1)def createIconWindDirection(self, obs):angle = obs.wind_dir.value()if angle >= 337.5 and angle < 22.5: # Nif self.settings.useInverseWind:return '↓'else:return '↑'elif angle >= 22.5 and angle < 67.5: # NEif self.settings.useInverseWind:return '↙'else:return '↗'elif angle >= 67.5 and angle < 112.5: # Eif self.settings.useInverseWind:return '←'else:return '→'elif angle >= 112.5 and angle < 157.5: # SEif self.settings.useInverseWind:return '↖'else:return '↘'elif angle >= 157.5 and angle < 202.5: # Sif self.settings.useInverseWind:return '↑'else:return '↓'elif angle >= 202.5 and angle < 247.5: # SWif self.settings.useInverseWind:return '↗'else:return '↙'elif angle >= 247.5 and angle < 292.5: # Wif self.settings.useInverseWind:return '→'else:return '←'else: # angle >= 292.5 and angle < 337.5 # NWif self.settings.useInverseWind:return '↘'else:return '↖'print('METARS: This should not happen')sys.exit(1)def createTextWindDirection(self, obs):compass = obs.wind_dir.compass()if not self.settings.useInverseWind:return compassif compass == 'N':return 'S'elif compass == 'NNE':return 'SSW'elif compass == 'NE':return 'SW'elif compass == 'ENE':return 'WSW'elif compass == 'E':return 'W'elif compass == 'ESE':return 'WNW'elif compass == 'SE':return 'NW'elif compass == 'SSE':return 'NNW'elif compass == 'S':return 'N'elif compass == 'SSW':return 'NNE'elif compass == 'SW':return 'NE'elif compass == 'WSW':return 'ENE'elif compass == 'W':return 'E'elif compass == 'WNW':return 'ESE'elif compass == 'NW':return 'SE'elif compass == 'NNW':return 'SSE'print('METARS: This should not happen')sys.exit(1)def createAngleWindDirection(self, obs):angle = obs.wind_dir.value()if self.settings.useInverseWind:angle += 180if angle >= 360:angle -= 360return '{}°'.format(angle)def createWindDirection(self, obs):# https://www.wpc.ncep.noaa.gov/dailywxmap/plottedwx.html# "The wind direction is plotted as the shaft of an arrow extending from the# station circle toward the direction from which the wind is blowing"# Here "inverse" may be more natural for modern users, showing the wind# as "from-to" arrowif self.settings.windDirType == 'angle':direction = self.createAngleWindDirection(obs)elif self.settings.windDirType == 'text':direction = self.createTextWindDirection(obs)elif self.settings.windDirType == 'icon':direction = self.createIconWindDirection(obs)else:print('METARS: Unknown wind direction type "{}"'.format(self.settings.windDirType))sys.exit(1)return directiondef extractObservations(self, obs):if obs.station_id:self.obs['station_id'] = obs.station_idif obs.time:self.obs['time'] = obs.time.isoformat()if obs.cycle:self.obs['cycle'] = obs.cycleif obs.wind_dir:self.obs['wind_dir'] = self.createWindDirection(obs)if obs.wind_speed:speed = obs.wind_speed.value(self.settings.speedUnit)self.obs['wind_speed'] = '{} {}'.format(round(speed), self.settings.speedSym)if obs.wind_gust:speedgust = obs.wind_gust.value(self.settings.speedUnit)self.obs['wind_gust'] = '{} {}'.format(round(speedgust), self.settings.speedSym)if obs.vis:distance = obs.vis.value(self.settings.distanceUnit)self.obs['vis'] = '{} {}'.format(round(distance), self.settings.distanceSym)if obs.temp:temp = obs.temp.value(self.settings.temperatureUnit)self.obs['temp'] = '{} {}'.format(round(temp,1), self.settings.temperatureSym)if obs.dewpt:dewpt = obs.dewpt.value(self.settings.temperatureUnit)self.obs['dewpt'] = '{} {}'.format(round(dewpt,1), self.settings.temperatureSym)if obs.press:pressure = obs.press.value(self.settings.pressureUnit)self.obs['press'] = '{} {}'.format(round(pressure), self.settings.pressureSym)if 'temp' in self.obs:tempInCelsius = obs.temp.value('C')if 'wind_speed' in self.obs:speedInKmh = obs.wind_speed.value('KMH')metricChill = self.getChillMetric(tempInCelsius, speedInKmh)if metricChill != None:twc = self.convertCelciusTo(metricChill)self.obs['twc'] = '{} {}'.format(round(twc,1), self.settings.temperatureSym)if 'wind_gust' in self.obs:speedInKmh = obs.wind_gust.value('KMH')metricChill = self.getChillMetric(tempInCelsius, speedInKmh)if metricChill != None:twc = self.convertCelciusTo(metricChill)self.obs['twcgust'] = '{} {}'.format(round(twc,1), self.settings.temperatureSym)# print(self.obs)def getStationData(self, station):metarurl = self.metarurl.format(station)try:page = urllib.request.urlopen(metarurl)readPage = page.read()except Exception as e:print('METARS url fetch: {}.'.format(e))sys.exit(1)stationData = str(readPage).split('\\n')return stationDatadef processMetars(self, blockSelect):metars = self.getStationData(self.settings.station)for metar in metars:self.obs.clear()# metar = 'METAR KEWR 111851Z VRB03G19KT 2SM R04R/3000VP6000FT TSRA BR FEW015 BKN040CB BKN065 OVC200 22/22 A2987 RMK AO2 PK WND 29028/1817 WSHFT 1812 TSB05RAB22 SLP114 FRQ LTGICCCCG TS OHD AND NW -N-E MOV NE P0013 T02270215'try:obs = Metar.Metar(metar)if blockSelect:cmd = 'notify-send -t 0 "{}"'.format(obs)self.runCommand(cmd)self.extractObservations(obs)weather = self.createWeatherString(obs)print(weather)except Metar.ParserError as e:passdef createWeatherString(self, obs):weather = ''if 'station_id' in self.obs:weather += self.obs['station_id'] + ':'else:weather += '?:'if self.settings.temperature:if 'temp' in self.obs:weather += ' ' + self.obs['temp']if self.settings.dewpoint:if 'dewpt' in self.obs:weather += ' dewpt ' + self.obs['dewpt']if self.settings.feelsLike:if 'twc' in self.obs:weather += ' feels ' + self.obs['twc']if 'twcgust' in self.obs:weather += ' gustfeels ' + self.obs['twcgust']if self.settings.wind:if 'wind_dir' in self.obs or 'wind_speed' in self.obs:weather += ' wind'if 'wind_dir' in self.obs:weather += ' ' + self.obs['wind_dir']if 'wind_dir' in self.obs and 'wind_speed' in self.obs:weather += ' at'if 'wind_speed' in self.obs:weather += ' ' + self.obs['wind_speed']if 'wind_gust' in self.obs:weather += ' gusts ' + self.obs['wind_gust']if self.settings.pressure:if 'press' in self.obs:weather += ' press ' + self.obs['press']if self.settings.visibility:if 'vis' in self.obs:weather += ' vis ' + self.obs['vis']return weatherdef run(self, blockSelect):self.processMetars(blockSelect)if __name__ == '__main__':settings = MetarsSettingsEnvironment()if not settings.isConfigured():print('METARS: Not configured.')sys.exit(1)settings.extract()metars = Metars(settings)if 'BLOCK_BUTTON' in os.environ:buttonType = os.environ['BLOCK_BUTTON']if buttonType == '1' or buttonType == '2' or buttonType == '3':metars.run(True)else:metars.run(False)else:metars.run(False)
#!/usr/bin/env python3# Required steps before running this scripts:# > sudo pip install python-metar# > sudo pacman -S libnotify# Possibly also:# > sudo pacman -S dunstimport osimport sys# Let's use json here for performance reasons:# https://stackoverflow.com/questions/988228/convert-a-string-representation-of-a-dictionary-to-a-dictionaryimport jsonimport datetimeimport subprocessimport urllib.requestfrom metar import Metarclass MetarsSettingsEnvironment:def isConfigured(self):# return Trueif not 'METARSSTATION' in os.environ:return Falseif not 'METARSURL' in os.environ:return Falseif not 'METARSENABLEMENTS' in os.environ:return Falseif not 'METARSCONFIGS' in os.environ:return Falsereturn Truedef extractAndUnpack(self, settings):try:extracted = json.loads(settings)except Exception as e:print('METARS extract 1: {}'.format(e))sys.exit(1)for k, v in extracted.items():try:setattr(self, k, v)except Exception as e:print('METARS extract 2: {}'.format(e))sys.exit(1)def extract(self):self.station = os.environ['METARSSTATION']self.metarurl = os.environ['METARSURL']enablements = os.environ['METARSENABLEMENTS']configs = os.environ['METARSCONFIGS']# self.station = 'EFHK'# self.metarurl = 'https://tgftp.nws.noaa.gov/data/observations/metar/stations/{}.TXT'# enablements = '{ "temperature": true, "dewpoint" : false, "feelsLike" : true, "wind" : true, "pressure" : false, "visibility" : false, "windDirType" : "icon", "useInverseWind" : false }'# configs = '{ "temperatureUnit" : "C", "temperatureSym" : "°C", "pressureUnit" : "HPA", "pressureSym" : "hPa", "speedUnit" : "MPS", "speedSym" : "m/s", "distanceUnit" : "KM", "distanceSym" : "km", "precipitationUnit" : "CM", "precipitationSym" : "cm"}'self.extractAndUnpack(enablements)self.extractAndUnpack(configs)class Metars:obs = {}settings = Nonemetarurl = 'https://tgftp.nws.noaa.gov/data/observations/metar/stations/{}.TXT'def __init__(self, settings):self.settings = settingsdef runCommand(self, command):retCode = 0retText = ''try:retText = subprocess.check_output(command, shell=True).decode('UTF-8')except subprocess.CalledProcessError as e:retCode = e.returncoderetText = e.output.decode('UTF-8')except:retCode = -999retText = 'ERROR: Unknown exception.'return retCode, retTextdef getChillMetric(self, temp, velocity): # temp = C, velocity = km/hif temp > 10.0 or velocity <= 4.8:return Noneexpt = velocity ** 0.16twc = 13.12 + (0.6215 * temp) - (11.37 * expt) + (0.3965 * temp * expt)return twcdef convertCelciusTo(self, temp):if self.settings.temperatureUnit == 'C':return tempelif self.settings.temperatureUnit == 'F':return (temp * 1.8) + 32elif self.settings.temperatureUnit == 'K':return temp + 273.15print('METARS: Unknown unit "{}"'.format(self.settings.temperatureUnit))sys.exit(1)def createIconWindDirection(self, obs):angle = obs.wind_dir.value()if angle >= 337.5 and angle < 22.5: # Nif self.settings.useInverseWind:return '↓'else:return '↑'elif angle >= 22.5 and angle < 67.5: # NEif self.settings.useInverseWind:return '↙'else:return '↗'elif angle >= 67.5 and angle < 112.5: # Eif self.settings.useInverseWind:return '←'else:return '→'elif angle >= 112.5 and angle < 157.5: # SEif self.settings.useInverseWind:return '↖'else:return '↘'elif angle >= 157.5 and angle < 202.5: # Sif self.settings.useInverseWind:return '↑'else:return '↓'elif angle >= 202.5 and angle < 247.5: # SWif self.settings.useInverseWind:return '↗'else:return '↙'elif angle >= 247.5 and angle < 292.5: # Wif self.settings.useInverseWind:return '→'else:return '←'else: # angle >= 292.5 and angle < 337.5 # NWif self.settings.useInverseWind:return '↘'else:return '↖'print('METARS: This should not happen')sys.exit(1)def createTextWindDirection(self, obs):compass = obs.wind_dir.compass()if not self.settings.useInverseWind:return compassif compass == 'N':return 'S'elif compass == 'NNE':return 'SSW'elif compass == 'NE':return 'SW'elif compass == 'ENE':return 'WSW'elif compass == 'E':return 'W'elif compass == 'ESE':return 'WNW'elif compass == 'SE':return 'NW'elif compass == 'SSE':return 'NNW'elif compass == 'S':return 'N'elif compass == 'SSW':return 'NNE'elif compass == 'SW':return 'NE'elif compass == 'WSW':return 'ENE'elif compass == 'W':return 'E'elif compass == 'WNW':return 'ESE'elif compass == 'NW':return 'SE'elif compass == 'NNW':return 'SSE'print('METARS: This should not happen')sys.exit(1)def createAngleWindDirection(self, obs):angle = obs.wind_dir.value()if self.settings.useInverseWind:angle += 180if angle >= 360:angle -= 360return '{}°'.format(angle)def createWindDirection(self, obs):# https://www.wpc.ncep.noaa.gov/dailywxmap/plottedwx.html# "The wind direction is plotted as the shaft of an arrow extending from the# station circle toward the direction from which the wind is blowing"# Here "inverse" may be more natural for modern users, showing the wind# as "from-to" arrowif self.settings.windDirType == 'angle':direction = self.createAngleWindDirection(obs)elif self.settings.windDirType == 'text':direction = self.createTextWindDirection(obs)elif self.settings.windDirType == 'icon':direction = self.createIconWindDirection(obs)else:print('METARS: Unknown wind direction type "{}"'.format(self.settings.windDirType))sys.exit(1)return directiondef extractObservations(self, obs):if obs.station_id:self.obs['station_id'] = obs.station_idif obs.time:self.obs['time'] = obs.time.isoformat()if obs.cycle:self.obs['cycle'] = obs.cycleif obs.wind_dir:self.obs['wind_dir'] = self.createWindDirection(obs)if obs.wind_speed:speed = obs.wind_speed.value(self.settings.speedUnit)self.obs['wind_speed'] = '{} {}'.format(round(speed), self.settings.speedSym)if obs.wind_gust:speedgust = obs.wind_gust.value(self.settings.speedUnit)self.obs['wind_gust'] = '{} {}'.format(round(speedgust), self.settings.speedSym)if obs.vis:distance = obs.vis.value(self.settings.distanceUnit)self.obs['vis'] = '{} {}'.format(round(distance), self.settings.distanceSym)if obs.temp:temp = obs.temp.value(self.settings.temperatureUnit)self.obs['temp'] = '{} {}'.format(round(temp,1), self.settings.temperatureSym)if obs.dewpt:dewpt = obs.dewpt.value(self.settings.temperatureUnit)self.obs['dewpt'] = '{} {}'.format(round(dewpt,1), self.settings.temperatureSym)if obs.press:pressure = obs.press.value(self.settings.pressureUnit)self.obs['press'] = '{} {}'.format(round(pressure), self.settings.pressureSym)if 'temp' in self.obs:tempInCelsius = obs.temp.value('C')if 'wind_speed' in self.obs:speedInKmh = obs.wind_speed.value('KMH')metricChill = self.getChillMetric(tempInCelsius, speedInKmh)if metricChill != None:twc = self.convertCelciusTo(metricChill)self.obs['twc'] = '{} {}'.format(round(twc,1), self.settings.temperatureSym)if 'wind_gust' in self.obs:speedInKmh = obs.wind_gust.value('KMH')metricChill = self.getChillMetric(tempInCelsius, speedInKmh)if metricChill != None:twc = self.convertCelciusTo(metricChill)self.obs['twcgust'] = '{} {}'.format(round(twc,1), self.settings.temperatureSym)# print(self.obs)def getStationData(self, station):metarurl = self.metarurl.format(station)try:page = urllib.request.urlopen(metarurl)readPage = page.read()except Exception as e:print('METARS url fetch: {}.'.format(e))sys.exit(1)stationData = str(readPage).split('\\n')return stationDatadef processMetars(self, blockSelect):metars = self.getStationData(self.settings.station)for metar in metars:self.obs.clear()# metar = 'METAR KEWR 111851Z VRB03G19KT 2SM R04R/3000VP6000FT TSRA BR FEW015 BKN040CB BKN065 OVC200 22/22 A2987 RMK AO2 PK WND 29028/1817 WSHFT 1812 TSB05RAB22 SLP114 FRQ LTGICCCCG TS OHD AND NW -N-E MOV NE P0013 T02270215'try:obs = Metar.Metar(metar)if blockSelect:cmd = 'notify-send -t 0 "{}"'.format(obs)self.runCommand(cmd)self.extractObservations(obs)weather = self.createWeatherString(obs)print(weather)except Metar.ParserError as e:passdef createWeatherString(self, obs):weather = ''if 'station_id' in self.obs:weather += self.obs['station_id'] + ':'else:weather += '?:'if self.settings.temperature:if 'temp' in self.obs:weather += ' ' + self.obs['temp']if self.settings.dewpoint:if 'dewpt' in self.obs:weather += ' dewpt ' + self.obs['dewpt']if self.settings.feelsLike:if 'twc' in self.obs:weather += ' feels ' + self.obs['twc']if 'twcgust' in self.obs:weather += ' gustfeels ' + self.obs['twcgust']if self.settings.wind:if 'wind_dir' in self.obs or 'wind_speed' in self.obs:weather += ' wind'if 'wind_dir' in self.obs:weather += ' ' + self.obs['wind_dir']if 'wind_dir' in self.obs and 'wind_speed' in self.obs:weather += ' at'if 'wind_speed' in self.obs:weather += ' ' + self.obs['wind_speed']if 'wind_gust' in self.obs:weather += ' gusts ' + self.obs['wind_gust']if self.settings.pressure:if 'press' in self.obs:weather += ' press ' + self.obs['press']if self.settings.visibility:if 'vis' in self.obs:weather += ' vis ' + self.obs['vis']return weatherdef run(self, blockSelect):self.processMetars(blockSelect)if __name__ == '__main__':settings = MetarsSettingsEnvironment()if not settings.isConfigured():print('METARS: Not configured.')sys.exit(1)settings.extract()metars = Metars(settings)if 'BLOCK_BUTTON' in os.environ:buttonType = os.environ['BLOCK_BUTTON']if buttonType == '1' or buttonType == '2' or buttonType == '3':metars.run(True)else:metars.run(False)else:metars.run(False)
#!/usr/bin/env sh# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.TYPE="${BLOCK_INSTANCE:-mem}"PERCENT="${PERCENT:-true}"awk -v type=$TYPE -v percent=$PERCENT '/^MemTotal:/ {mem_total=$2}/^MemFree:/ {mem_free=$2}/^Buffers:/ {mem_free+=$2}/^Cached:/ {mem_free+=$2}/^SwapTotal:/ {swap_total=$2}/^SwapFree:/ {swap_free=$2}END {if (type == "swap") {free=swap_free/1024/1024used=(swap_total-swap_free)/1024/1024total=swap_total/1024/1024} else {free=mem_free/1024/1024used=(mem_total-mem_free)/1024/1024total=mem_total/1024/1024}pct=0if (total > 0) {pct=used/total*100}# full textif (percent == "true" ) {printf("%.1fG/%.1fG (%.f%%)\n", used, total, pct)} else {printf("%.1fG/%.1fG\n", used, total)}# short textprintf("%.f%%\n", pct)# colorif (pct > 90) {print("#FF0000")} else if (pct > 80) {print("#FFAE00")} else if (pct > 70) {print("#FFF600")}}' /proc/meminfo
#!/usr/bin/env sh# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.TYPE="${BLOCK_INSTANCE:-mem}"PERCENT="${PERCENT:-true}"awk -v type=$TYPE -v percent=$PERCENT '/^MemTotal:/ {mem_total=$2}/^MemFree:/ {mem_free=$2}/^Buffers:/ {mem_free+=$2}/^Cached:/ {mem_free+=$2}/^SwapTotal:/ {swap_total=$2}/^SwapFree:/ {swap_free=$2}END {if (type == "swap") {free=swap_free/1024/1024used=(swap_total-swap_free)/1024/1024total=swap_total/1024/1024} else {free=mem_free/1024/1024used=(mem_total-mem_free)/1024/1024total=mem_total/1024/1024}pct=0if (total > 0) {pct=used/total*100}# full textif (percent == "true" ) {printf("%.1fG/%.1fG (%.f%%)\n", used, total, pct)} else {printf("%.1fG/%.1fG\n", used, total)}# short textprintf("%.f%%\n", pct)# colorif (pct > 90) {print("#FF0000")} else if (pct > 80) {print("#FFAE00")} else if (pct > 70) {print("#FFF600")}}' /proc/meminfo
#!/usr/bin/env perl# Copyright (C) 2014 Tony Crisci <tony@dubstepdish.com># Copyright (C) 2015 Thiago Perrotta <perrotta dot thiago at poli dot ufrj dot br># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# For all media players except mpd/cmus/rhythmbox, MPRIS support should be# enabled and the playerctl binary should be in your path.# See https://github.com/acrisci/playerctl# Set instance=NAME in the i3blocks configuration to specify a music player# (playerctl will attempt to connect to org.mpris.MediaPlayer2.[NAME] on your# DBus session). If instance is empty, playerctl will connect to the first# supported media player it finds.use Time::HiRes qw(usleep);use Env qw(BLOCK_INSTANCE);use constant DELAY => 50; # Delay in ms to let network-based players (spotify) reflect new data.use constant SPOTIFY_STR => 'spotify';my @metadata = ();my $player_arg = "";if ($BLOCK_INSTANCE) {$player_arg = "--player='$BLOCK_INSTANCE'";}sub buttons {my $method = shift;if($method eq 'mpd') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("mpc prev &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("mpc toggle &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("mpc next &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 4) {system("mpc volume +10 &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 5) {system("mpc volume -10 &>/dev/null");}} elsif ($method eq 'cmus') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("cmus-remote --prev");} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("cmus-remote --pause");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("cmus-remote --next");}} elsif ($method eq 'playerctl') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("playerctl $player_arg previous");usleep(DELAY * 1000) if $BLOCK_INSTANCE eq SPOTIFY_STR;} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("playerctl $player_arg play-pause");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("playerctl $player_arg next");usleep(DELAY * 1000) if $BLOCK_INSTANCE eq SPOTIFY_STR;} elsif ($ENV{'BLOCK_BUTTON'} == 4) {system("playerctl $player_arg volume 0.01+");} elsif ($ENV{'BLOCK_BUTTON'} == 5) {system("playerctl $player_arg volume 0.01-");}} elsif ($method eq 'rhythmbox') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("rhythmbox-client --previous");} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("rhythmbox-client --play-pause");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("rhythmbox-client --next");}}}sub cmus {my @cmus = split /^/, qx(cmus-remote -Q);if ($? == 0) {foreach my $line (@cmus) {my @data = split /\s/, $line;if (shift @data eq 'tag') {my $key = shift @data;my $value = join ' ', @data;@metadata[0] = $value if $key eq 'artist';@metadata[1] = $value if $key eq 'title';}}if (@metadata) {buttons('cmus');# metadata found so we are doneprint(join ' - ', @metadata);print("\n");exit 0;}}}sub mpd {my $data = qx(mpc current);if (not $data eq '') {buttons("mpd");print($data);exit 0;}}sub playerctl {buttons('playerctl');my $artist = qx(playerctl $player_arg metadata artist 2>/dev/null);chomp $artist;# exit status will be nonzero when playerctl cannot find your playerexit(0) if $? || $artist eq '(null)';push(@metadata, $artist) if $artist;my $title = qx(playerctl $player_arg metadata title);exit(0) if $? || $title eq '(null)';push(@metadata, $title) if $title;print(join(" - ", @metadata)) if @metadata;}sub rhythmbox {buttons('rhythmbox');my $data = qx(rhythmbox-client --print-playing --no-start);print($data);}if ($player_arg =~ /mpd/) {mpd;}elsif ($player_arg =~ /cmus/) {cmus;}elsif ($player_arg =~ /rhythmbox/) {rhythmbox;}else {playerctl;}print("\n");
#!/usr/bin/env perl# Copyright (C) 2014 Tony Crisci <tony@dubstepdish.com># Copyright (C) 2015 Thiago Perrotta <perrotta dot thiago at poli dot ufrj dot br># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# For all media players except mpd/cmus/rhythmbox, MPRIS support should be# enabled and the playerctl binary should be in your path.# See https://github.com/acrisci/playerctl# Set instance=NAME in the i3blocks configuration to specify a music player# (playerctl will attempt to connect to org.mpris.MediaPlayer2.[NAME] on your# DBus session). If instance is empty, playerctl will connect to the first# supported media player it finds.use Time::HiRes qw(usleep);use Env qw(BLOCK_INSTANCE);use constant DELAY => 50; # Delay in ms to let network-based players (spotify) reflect new data.use constant SPOTIFY_STR => 'spotify';my @metadata = ();my $player_arg = "";if ($BLOCK_INSTANCE) {$player_arg = "--player='$BLOCK_INSTANCE'";}sub buttons {my $method = shift;if($method eq 'mpd') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("mpc prev &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("mpc toggle &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("mpc next &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 4) {system("mpc volume +10 &>/dev/null");} elsif ($ENV{'BLOCK_BUTTON'} == 5) {system("mpc volume -10 &>/dev/null");}} elsif ($method eq 'cmus') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("cmus-remote --prev");} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("cmus-remote --pause");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("cmus-remote --next");}} elsif ($method eq 'playerctl') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("playerctl $player_arg previous");usleep(DELAY * 1000) if $BLOCK_INSTANCE eq SPOTIFY_STR;} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("playerctl $player_arg play-pause");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("playerctl $player_arg next");usleep(DELAY * 1000) if $BLOCK_INSTANCE eq SPOTIFY_STR;} elsif ($ENV{'BLOCK_BUTTON'} == 4) {system("playerctl $player_arg volume 0.01+");} elsif ($ENV{'BLOCK_BUTTON'} == 5) {system("playerctl $player_arg volume 0.01-");}} elsif ($method eq 'rhythmbox') {if ($ENV{'BLOCK_BUTTON'} == 1) {system("rhythmbox-client --previous");} elsif ($ENV{'BLOCK_BUTTON'} == 2) {system("rhythmbox-client --play-pause");} elsif ($ENV{'BLOCK_BUTTON'} == 3) {system("rhythmbox-client --next");}}}sub cmus {my @cmus = split /^/, qx(cmus-remote -Q);if ($? == 0) {foreach my $line (@cmus) {my @data = split /\s/, $line;if (shift @data eq 'tag') {my $key = shift @data;my $value = join ' ', @data;@metadata[0] = $value if $key eq 'artist';@metadata[1] = $value if $key eq 'title';}}if (@metadata) {buttons('cmus');# metadata found so we are doneprint(join ' - ', @metadata);print("\n");exit 0;}}}sub mpd {my $data = qx(mpc current);if (not $data eq '') {buttons("mpd");print($data);exit 0;}}sub playerctl {buttons('playerctl');my $artist = qx(playerctl $player_arg metadata artist 2>/dev/null);chomp $artist;# exit status will be nonzero when playerctl cannot find your playerexit(0) if $? || $artist eq '(null)';push(@metadata, $artist) if $artist;my $title = qx(playerctl $player_arg metadata title);exit(0) if $? || $title eq '(null)';push(@metadata, $title) if $title;print(join(" - ", @metadata)) if @metadata;}sub rhythmbox {buttons('rhythmbox');my $data = qx(rhythmbox-client --print-playing --no-start);print($data);}if ($player_arg =~ /mpd/) {mpd;}elsif ($player_arg =~ /cmus/) {cmus;}elsif ($player_arg =~ /rhythmbox/) {rhythmbox;}else {playerctl;}print("\n");
#!/usr/bin/env sh# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.load="$(cut -d ' ' -f1 /proc/loadavg)"cpus="$(nproc)"# full textecho "$load"# short textecho "$load"# color if load is too highawk -v cpus=$cpus -v cpuload=$load 'BEGIN {if (cpus <= cpuload) {print "#FF0000";exit 33;}}'
#!/usr/bin/env sh# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.load="$(cut -d ' ' -f1 /proc/loadavg)"cpus="$(nproc)"# full textecho "$load"# short textecho "$load"# color if load is too highawk -v cpus=$cpus -v cpuload=$load 'BEGIN {if (cpus <= cpuload) {print "#FF0000";exit 33;}}'
#!/usr/bin/env bashKCONTEXT=$(kubectl config current-context 2>/dev/null)if [[ $?=="0" ]]; thenCC=$(kubectl config view -ojsonpath='{..current-context}')KNAMESPACE=$(kubectl config view -ojsonpath="{.Contexts[?(@.Name==\"$CC\")]..namespace}")echo "☸ $KCONTEXT/$KNAMESPACE ☸"echo "☸ $KCONTEXT/$KNAMESPACE ☸"echo \#4040FF # colorfi
#!/usr/bin/env bashKCONTEXT=$(kubectl config current-context 2>/dev/null)if [[ $?=="0" ]]; thenCC=$(kubectl config view -ojsonpath='{..current-context}')KNAMESPACE=$(kubectl config view -ojsonpath="{.Contexts[?(@.Name==\"$CC\")]..namespace}")echo "☸ $KCONTEXT/$KNAMESPACE ☸"echo "☸ $KCONTEXT/$KNAMESPACE ☸"echo \#4040FF # colorfi
#!/usr/bin/env perl## Copyright 2014 Marcelo Cerri <mhcerri at gmail dot com>## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.use strict;use warnings;use utf8;use Getopt::Long;use File::Basename;# Default valuesmy $indicator = $ENV{BLOCK_INSTANCE} || $ENV{KEY} || "CAPS";my $text_on = $ENV{TEXT_ON} || $indicator;my $text_off = $ENV{TEXT_OFF} || $indicator;my $color_on = $ENV{COLOR_ON} || "#00FF00";my $color_off = $ENV{COLOR_OFF} || "#222222";my $bg_color_on = $ENV{BG_COLOR_ON};my $bg_color_off = $ENV{BG_COLOR_OFF};my $hide = $ENV{HIDE_WHEN_OFF} || 0;sub help {my $program = basename($0);printf "Usage: %s [-c <color on>] [-C <color off>] [-b <bg color on>] [-B <bg color off>] [--hide]\n", $program;printf " -c <color on>: hex color to use when indicator is on\n";printf " -C <color off>: hex color to use when indicator is off\n";printf " -b <background color on>: hex color to use when indicator is on\n";printf " -B <background color off>: hex color to use when indicator is off\n";printf " --hide: don't output anything when indicator is off\n";printf "\n";printf "Note: environment variable \$BLOCK_INSTANCE should be one of:\n";printf " CAPS, NUM (default is CAPS).\n";exit 0;}Getopt::Long::config qw(no_ignore_case);GetOptions("help|h" => \&help,"c=s" => \$color_on,"C=s" => \$color_off,"b=s" => \$bg_color_on,"B=s" => \$bg_color_off,"hide" => \$hide) or exit 1;# Key mappingmy %indicators = (CAPS => 0x00000001,NUM => 0x00000002,);# Retrieve key flagsmy $mask = 0;open(XSET, "xset -q |") or die;while (<XSET>) {if (/LED mask:\s*([0-9a-f]+)/) {$mask = hex $1;last;}}close(XSET);# Determine if indicator is on or offmy $indicator_status = ($indicators{$indicator} || 0) & $mask;# Exit if --hide and indicator is offif ($hide and !$indicator_status) {exit 0}# Output$indicator = $indicator_status ? $text_on : $text_off;my $fg_color = $indicator_status ? $color_on : $color_off;my $bg_color = $indicator_status ? $bg_color_on : $bg_color_off;if (defined $bg_color) {printf "<span color='%s' bgcolor='%s'>%s</span>\n", $fg_color, $bg_color, $indicator;} else {printf "<span color='%s'>%s</span>\n", $fg_color, $indicator;}exit 0
#!/usr/bin/env perl## Copyright 2014 Marcelo Cerri <mhcerri at gmail dot com>## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.use strict;use warnings;use utf8;use Getopt::Long;use File::Basename;# Default valuesmy $indicator = $ENV{BLOCK_INSTANCE} || $ENV{KEY} || "CAPS";my $text_on = $ENV{TEXT_ON} || $indicator;my $text_off = $ENV{TEXT_OFF} || $indicator;my $color_on = $ENV{COLOR_ON} || "#00FF00";my $color_off = $ENV{COLOR_OFF} || "#222222";my $bg_color_on = $ENV{BG_COLOR_ON};my $bg_color_off = $ENV{BG_COLOR_OFF};my $hide = $ENV{HIDE_WHEN_OFF} || 0;sub help {my $program = basename($0);printf "Usage: %s [-c <color on>] [-C <color off>] [-b <bg color on>] [-B <bg color off>] [--hide]\n", $program;printf " -c <color on>: hex color to use when indicator is on\n";printf " -C <color off>: hex color to use when indicator is off\n";printf " -b <background color on>: hex color to use when indicator is on\n";printf " -B <background color off>: hex color to use when indicator is off\n";printf " --hide: don't output anything when indicator is off\n";printf "\n";printf "Note: environment variable \$BLOCK_INSTANCE should be one of:\n";printf " CAPS, NUM (default is CAPS).\n";exit 0;}Getopt::Long::config qw(no_ignore_case);GetOptions("help|h" => \&help,"c=s" => \$color_on,"C=s" => \$color_off,"b=s" => \$bg_color_on,"B=s" => \$bg_color_off,"hide" => \$hide) or exit 1;# Key mappingmy %indicators = (CAPS => 0x00000001,NUM => 0x00000002,);# Retrieve key flagsmy $mask = 0;open(XSET, "xset -q |") or die;while (<XSET>) {if (/LED mask:\s*([0-9a-f]+)/) {$mask = hex $1;last;}}close(XSET);# Determine if indicator is on or offmy $indicator_status = ($indicators{$indicator} || 0) & $mask;# Exit if --hide and indicator is offif ($hide and !$indicator_status) {exit 0}# Output$indicator = $indicator_status ? $text_on : $text_off;my $fg_color = $indicator_status ? $color_on : $color_off;my $bg_color = $indicator_status ? $bg_color_on : $bg_color_off;if (defined $bg_color) {printf "<span color='%s' bgcolor='%s'>%s</span>\n", $fg_color, $bg_color, $indicator;} else {printf "<span color='%s'>%s</span>\n", $fg_color, $indicator;}exit 0
#!/usr/bin/env bash# Copyright 2019 Matej Čamaj <camaj at protonmail dot com>## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# See https://upower.freedesktop.org/docs/KbdBacklight.htmlfunction get_brightness {dbus-send --system --type=method_call --print-reply\--dest="org.freedesktop.UPower" \"/org/freedesktop/UPower/KbdBacklight" \"org.freedesktop.UPower.KbdBacklight.$1" \| awk 'FNR==2{print $2}'}brightness=$(get_brightness "GetBrightness")max_brightness=$(get_brightness "GetMaxBrightness")if [ "$brightness" -eq "$max_brightness" ]; thennew_brightness=0elsenew_brightness=$((brightness + 1))fidbus-send --system --type=method_call \--dest="org.freedesktop.UPower" \"/org/freedesktop/UPower/KbdBacklight" \"org.freedesktop.UPower.KbdBacklight.SetBrightness" int32:$new_brightness
#!/usr/bin/env bash# Copyright 2019 Matej Čamaj <camaj at protonmail dot com>## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# See https://upower.freedesktop.org/docs/KbdBacklight.htmlfunction get_brightness {dbus-send --system --type=method_call --print-reply\--dest="org.freedesktop.UPower" \"/org/freedesktop/UPower/KbdBacklight" \"org.freedesktop.UPower.KbdBacklight.$1" \| awk 'FNR==2{print $2}'}brightness=$(get_brightness "GetBrightness")max_brightness=$(get_brightness "GetMaxBrightness")if [ "$brightness" -eq "$max_brightness" ]; thennew_brightness=0elsenew_brightness=$((brightness + 1))fidbus-send --system --type=method_call \--dest="org.freedesktop.UPower" \"/org/freedesktop/UPower/KbdBacklight" \"org.freedesktop.UPower.KbdBacklight.SetBrightness" int32:$new_brightness
#!/usr/bin/env bash# Copyright 2016 Patrick Haun# Edited: Denis Kadyshev## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.setxkbmap -query | awk 'BEGIN{layout="";variant=""}/^layout/{layout=$2}/^variant/{variant=" ("$2")"}END{printf("%s%s",layout,variant)}'
#!/usr/bin/env bash# Copyright 2016 Patrick Haun# Edited: Denis Kadyshev## This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.setxkbmap -query | awk 'BEGIN{layout="";variant=""}/^layout/{layout=$2}/^variant/{variant=" ("$2")"}END{printf("%s%s",layout,variant)}'
#!/bin/bash## kbdd_layout is a script that parse layout with kbdd in real time# Copyright (C) 2016,2019 Anton Karmanov <bergentroll@insiberia.net>## This program 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 any# later version.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# Matches first 3 letters of layout name.MATCH='\w{3}'# Matches short layout name.#MATCH='\w*'# Matches full layout name.#MATCH='\w*(\s\(.*\))?'# Restart kbdd to apply layout changes on block reload.killall kbdd 2>/dev/nullkbdd >/dev/null || exit 1# Get initial state of layoutN=$( dbus-send --print-reply=literal --dest=ru.gentoo.KbddService\/ru/gentoo/KbddService ru.gentoo.kbdd.getCurrentLayout 2>/dev/null |\sed -un 's/^.*uint32 //p' )# In case dbus service wasn't available yet, poll until service is ready.while [[ -z "$N" ]]; dosleep .1N=$( dbus-send --print-reply=literal --dest=ru.gentoo.KbddService\/ru/gentoo/KbddService ru.gentoo.kbdd.getCurrentLayout 2>/dev/null |\sed -un 's/^.*uint32 //p' )donedbus-send --print-reply=literal --dest=ru.gentoo.KbddService \/ru/gentoo/KbddService ru.gentoo.kbdd.getLayoutName uint32:"$N" |\grep -Po "${MATCH}" | head -n1# Parse dbus output.dbus-monitor "interface='ru.gentoo.kbdd',member='layoutNameChanged'" |\grep -Po --line-buffered "(?<=string \")${MATCH}"
#!/bin/bash## kbdd_layout is a script that parse layout with kbdd in real time# Copyright (C) 2016,2019 Anton Karmanov <bergentroll@insiberia.net>## This program 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 any# later version.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# Matches first 3 letters of layout name.MATCH='\w{3}'# Matches short layout name.#MATCH='\w*'# Matches full layout name.#MATCH='\w*(\s\(.*\))?'# Restart kbdd to apply layout changes on block reload.killall kbdd 2>/dev/nullkbdd >/dev/null || exit 1# Get initial state of layoutN=$( dbus-send --print-reply=literal --dest=ru.gentoo.KbddService\/ru/gentoo/KbddService ru.gentoo.kbdd.getCurrentLayout 2>/dev/null |\sed -un 's/^.*uint32 //p' )# In case dbus service wasn't available yet, poll until service is ready.while [[ -z "$N" ]]; dosleep .1N=$( dbus-send --print-reply=literal --dest=ru.gentoo.KbddService\/ru/gentoo/KbddService ru.gentoo.kbdd.getCurrentLayout 2>/dev/null |\sed -un 's/^.*uint32 //p' )donedbus-send --print-reply=literal --dest=ru.gentoo.KbddService \/ru/gentoo/KbddService ru.gentoo.kbdd.getLayoutName uint32:"$N" |\grep -Po "${MATCH}" | head -n1# Parse dbus output.dbus-monitor "interface='ru.gentoo.kbdd',member='layoutNameChanged'" |\grep -Po --line-buffered "(?<=string \")${MATCH}"
#!/usr/bin/env bash# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------# Use the provided interface, otherwise the device used for the default route.IF="${IFACE:-$BLOCK_INSTANCE}"IF="${IF:-$(ip route | awk '/^default/ { print $5 ; exit }')}"# Exit if there is no default route[[ -z "$IF" ]] && exit#------------------------------------------------------------------------# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.[[ ! -d /sys/class/net/${IF} ]] && exit#------------------------------------------------------------------------AF=${ADDRESS_FAMILY:-inet6?}LABEL="${LABEL:-}"for flag in "$1" "$2"; docase "$flag" in-4)AF=inet ;;-6)AF=inet6 ;;-L)if [[ "$IF" = "" ]]; thenLABEL="iface"elseLABEL="$IF:"fi ;;esacdoneif [[ "$IF" = "" ]] || [[ "$(cat /sys/class/net/$IF/operstate)" = 'down' ]]; thenecho "${LABEL} down" # full textecho "${LABEL} down" # short textecho \#FF0000 # colorexitfi# if no interface is found, use the first device with a global scopeIPADDR=$(ip addr show $IF | perl -n -e "/$AF ([^ \/]+).* scope global/ && print \$1 and exit")case $BLOCK_BUTTON in3) echo -n "$IPADDR" | xclip -q -se c ;;esacif [[ "${display_wifi_name}" == "1" ]];then# try to guess the wifi nameif command -v iw > /dev/null && iw $IF info > /dev/null 2>&1;thenWIFI_NAME=$(iw $IF info | grep -Po '(?<=ssid ).*' | tr -d " \t\n\r")if [[ $BLOCK_BUTTON -eq 1 ]];thenmessage="$LABEL $WIFI_NAME ($IPADDR)"elsemessage="$LABEL $WIFI_NAME"fielsemessage="$LABEL $IPADDR"fielsemessage="$LABEL $IPADDR"fi#------------------------------------------------------------------------echo "$message"
#!/usr/bin/env bash# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------# Use the provided interface, otherwise the device used for the default route.IF="${IFACE:-$BLOCK_INSTANCE}"IF="${IF:-$(ip route | awk '/^default/ { print $5 ; exit }')}"# Exit if there is no default route[[ -z "$IF" ]] && exit#------------------------------------------------------------------------# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.[[ ! -d /sys/class/net/${IF} ]] && exit#------------------------------------------------------------------------AF=${ADDRESS_FAMILY:-inet6?}LABEL="${LABEL:-}"for flag in "$1" "$2"; docase "$flag" in-4)AF=inet ;;-6)AF=inet6 ;;-L)if [[ "$IF" = "" ]]; thenLABEL="iface"elseLABEL="$IF:"fi ;;esacdoneif [[ "$IF" = "" ]] || [[ "$(cat /sys/class/net/$IF/operstate)" = 'down' ]]; thenecho "${LABEL} down" # full textecho "${LABEL} down" # short textecho \#FF0000 # colorexitfi# if no interface is found, use the first device with a global scopeIPADDR=$(ip addr show $IF | perl -n -e "/$AF ([^ \/]+).* scope global/ && print \$1 and exit")case $BLOCK_BUTTON in3) echo -n "$IPADDR" | xclip -q -se c ;;esacif [[ "${display_wifi_name}" == "1" ]];then# try to guess the wifi nameif command -v iw > /dev/null && iw $IF info > /dev/null 2>&1;thenWIFI_NAME=$(iw $IF info | grep -Po '(?<=ssid ).*' | tr -d " \t\n\r")if [[ $BLOCK_BUTTON -eq 1 ]];thenmessage="$LABEL $WIFI_NAME ($IPADDR)"elsemessage="$LABEL $WIFI_NAME"fielsemessage="$LABEL $IPADDR"fielsemessage="$LABEL $IPADDR"fi#------------------------------------------------------------------------echo "$message"
#!/usr/bin/env bash# Author: Knwhile :doID=$(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}')if [[ $1 ]]thenTITLE=$(xprop -id $ID -len $1 | awk '/_NET_WM_NAME/{$1=$2="";print}' | cut -d'"' -f2)echo "$TITLE"elseTITLE=$(xprop -id $ID | awk '/_NET_WM_NAME/{$1=$2="";print}' | cut -d'"' -f2)echo "$TITLE"fidone
#!/usr/bin/env bash# Author: Knwhile :doID=$(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}')if [[ $1 ]]thenTITLE=$(xprop -id $ID -len $1 | awk '/_NET_WM_NAME/{$1=$2="";print}' | cut -d'"' -f2)echo "$TITLE"elseTITLE=$(xprop -id $ID | awk '/_NET_WM_NAME/{$1=$2="";print}' | cut -d'"' -f2)echo "$TITLE"fidone
#!/usr/bin/env perl# This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.use strict;use warnings;use utf8;use Getopt::Long;# default valuesmy $t_warn = $ENV{T_WARN} || 70;my $t_crit = $ENV{T_CRIT} || 90;my $gpu_brand = $ENV{GPU_BRAND} || "NVIDIA";my $gpu_usage = -1;my $gpu_mem = -1;my $gpu_video = -1;my $gpu_pcie = -1;my $full_text = "";sub help {print "Usage: gpu-load [-w <warning>] [-c <critical>]\n";print "-w <percent>: warning threshold to become amber\n";print "-c <percent>: critical threshold to become red\n";exit 0;}GetOptions("help|h" => \&help,"w=i" => \$t_warn,"c=i" => \$t_crit);# Get GPU usage from nvidia-settingsif ($gpu_brand eq "NVIDIA") {open (NVS, 'nvidia-settings -q GPUUtilization -t |') or die;while (<NVS>) {if (/^[a-zA-Z]*=(\d+), [a-zA-Z]*=(\d+), [a-zA-Z]*=(\d+), [a-zA-Z]*=(\d+)$/) {$gpu_usage = $1;$gpu_mem = $2;$gpu_video = $3;$gpu_pcie = $4;last;}}close(NVS);$full_text = sprintf "%.0f%% %.0f%% %.0f%% %.0f%%\n", $gpu_usage, $gpu_mem, $gpu_video, $gpu_pcie;}# For AMD, get from radeontopelsif ($gpu_brand eq "AMD") {open (AMD, 'radeontop -d - -l 1 |') or die;while (<AMD>) {if (/^.*[gpu] (\d+)\.\d+%.*.*[vram] (\d+)\.\d+%.*$/) {$gpu_usage = $1;$gpu_mem = $2;last;}}close(AMD);$full_text = sprintf "%.0f%% %.0f%%\n", $gpu_usage, $gpu_mem;}$gpu_usage eq -1 and die 'Can\'t find GPU information';# Print full_text, short_textprint $full_text;printf "%.0f%%\n", $gpu_usage;# Print color, if neededif ($gpu_usage >= $t_crit || $gpu_mem >= $t_crit || $gpu_video >= $t_crit || $gpu_pcie >= $t_crit) {print "#FF0000\n";exit 33;} elsif ($gpu_usage >= $t_warn || $gpu_mem >= $t_warn || $gpu_video >= $t_warn || $gpu_pcie >= $t_warn) {print "#FFBF00\n";}exit 0;
#!/usr/bin/env perl# This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.use strict;use warnings;use utf8;use Getopt::Long;# default valuesmy $t_warn = $ENV{T_WARN} || 70;my $t_crit = $ENV{T_CRIT} || 90;my $gpu_brand = $ENV{GPU_BRAND} || "NVIDIA";my $gpu_usage = -1;my $gpu_mem = -1;my $gpu_video = -1;my $gpu_pcie = -1;my $full_text = "";sub help {print "Usage: gpu-load [-w <warning>] [-c <critical>]\n";print "-w <percent>: warning threshold to become amber\n";print "-c <percent>: critical threshold to become red\n";exit 0;}GetOptions("help|h" => \&help,"w=i" => \$t_warn,"c=i" => \$t_crit);# Get GPU usage from nvidia-settingsif ($gpu_brand eq "NVIDIA") {open (NVS, 'nvidia-settings -q GPUUtilization -t |') or die;while (<NVS>) {if (/^[a-zA-Z]*=(\d+), [a-zA-Z]*=(\d+), [a-zA-Z]*=(\d+), [a-zA-Z]*=(\d+)$/) {$gpu_usage = $1;$gpu_mem = $2;$gpu_video = $3;$gpu_pcie = $4;last;}}close(NVS);$full_text = sprintf "%.0f%% %.0f%% %.0f%% %.0f%%\n", $gpu_usage, $gpu_mem, $gpu_video, $gpu_pcie;}# For AMD, get from radeontopelsif ($gpu_brand eq "AMD") {open (AMD, 'radeontop -d - -l 1 |') or die;while (<AMD>) {if (/^.*[gpu] (\d+)\.\d+%.*.*[vram] (\d+)\.\d+%.*$/) {$gpu_usage = $1;$gpu_mem = $2;last;}}close(AMD);$full_text = sprintf "%.0f%% %.0f%%\n", $gpu_usage, $gpu_mem;}$gpu_usage eq -1 and die 'Can\'t find GPU information';# Print full_text, short_textprint $full_text;printf "%.0f%%\n", $gpu_usage;# Print color, if neededif ($gpu_usage >= $t_crit || $gpu_mem >= $t_crit || $gpu_video >= $t_crit || $gpu_pcie >= $t_crit) {print "#FF0000\n";exit 33;} elsif ($gpu_usage >= $t_warn || $gpu_mem >= $t_warn || $gpu_video >= $t_warn || $gpu_pcie >= $t_warn) {print "#FFBF00\n";}exit 0;
#!/usr/bin/env bashgo version 2>/dev/null | awk '{ gsub("go", ""); print $2 }'
#!/usr/bin/env python3"""A Github block for displaying notifications in i3 using i3blocks"""__author__ = "Adin Hodovic <hodovicadin@gmail.com>"__copyright__ = "Copyright (c) 2020 Adin Hodovic"__license__ = "MIT"__version__ = "1.0.0"import jsonimport osimport webbrowserdef get_notifications():notifications = len(json.loads(os.popen("gh api notifications").read()))if notifications > 0:return {"full_text": f"<span font='Font Awesome 5 Free Solid'> {notifications}</span>"}return {"full_text": "<span font='Font Awesome 5 Free Solid'></span>"}def clicked():"""Returns True if the button was clicked"""button = "BLOCK_BUTTON" in os.environ and os.environ["BLOCK_BUTTON"]return bool(button)if clicked():webbrowser.open("https://github.com/notifications")print(json.dumps(get_notifications()))
#!/usr/bin/env python3"""A Github block for displaying notifications in i3 using i3blocks"""__author__ = "Adin Hodovic <hodovicadin@gmail.com>"__copyright__ = "Copyright (c) 2020 Adin Hodovic"__license__ = "MIT"__version__ = "1.0.0"import jsonimport osimport webbrowserdef get_notifications():notifications = len(json.loads(os.popen("gh api notifications").read()))if notifications > 0:return {"full_text": f"<span font='Font Awesome 5 Free Solid'> {notifications}</span>"}return {"full_text": "<span font='Font Awesome 5 Free Solid'></span>"}def clicked():"""Returns True if the button was clicked"""button = "BLOCK_BUTTON" in os.environ and os.environ["BLOCK_BUTTON"]return bool(button)if clicked():webbrowser.open("https://github.com/notifications")print(json.dumps(get_notifications()))
#!/usr/bin/env bash# Copyright (C) 2021 Max Z. Tan# This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.color=$BLOCK_INSTANCEif [ -z "${SWAY}" ]; then# sleep to cater to grabc startup timesleep 0.5value=$(grabc 2>/dev/null)if [ "${CLIPBOARD}" ]; theni3-msg -q exec "xclip -sel clip < <(echo -n \\$value)"fielsevalue=$(grim -g "$(slurp -p -b '#00000000')" -t ppm - \| convert - -format '%[pixel:s]' info:- \| awk -F '[(,)]' '{printf("#%02x%02x%02x",$2,$3,$4)}')if [ "${CLIPBOARD}" ]; thenswaymsg -q exec wl-copy "\\$value"fififull_text="<span foreground=\"$value\"></span><span foreground=\"$color\">$value</span>"echo $full_text
#!/usr/bin/env bash# Copyright (C) 2021 Max Z. Tan# This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.color=$BLOCK_INSTANCEif [ -z "${SWAY}" ]; then# sleep to cater to grabc startup timesleep 0.5value=$(grabc 2>/dev/null)if [ "${CLIPBOARD}" ]; theni3-msg -q exec "xclip -sel clip < <(echo -n \\$value)"fielsevalue=$(grim -g "$(slurp -p -b '#00000000')" -t ppm - \| convert - -format '%[pixel:s]' info:- \| awk -F '[(,)]' '{printf("#%02x%02x%02x",$2,$3,$4)}')if [ "${CLIPBOARD}" ]; thenswaymsg -q exec wl-copy "\\$value"fififull_text="<span foreground=\"$value\"></span><span foreground=\"$color\">$value</span>"echo $full_text
#!/usr/bin/env bash# Copyright (C) 2018 borgified <borgified@gmail.com># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------INTERFACE="${INTERFACE:-wlan0}"#------------------------------------------------------------------------# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.[[ ! -d /sys/class/net/${INTERFACE}/wireless ]] ||[[ "$(cat /sys/class/net/$INTERFACE/operstate)" = 'down' ]] && exit#------------------------------------------------------------------------ESSID=$(/sbin/iwconfig $INTERFACE | perl -n -e'/ESSID:"(.*?)"/ && print $1')#------------------------------------------------------------------------echo $ESSID # full textecho $ESSID # short text
#!/usr/bin/env bash# Copyright (C) 2018 borgified <borgified@gmail.com># Copyright (C) 2014 Alexander Keller <github@nycroth.com># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.#------------------------------------------------------------------------INTERFACE="${INTERFACE:-wlan0}"#------------------------------------------------------------------------# As per #36 -- It is transparent: e.g. if the machine has no battery or wireless# connection (think desktop), the corresponding block should not be displayed.[[ ! -d /sys/class/net/${INTERFACE}/wireless ]] ||[[ "$(cat /sys/class/net/$INTERFACE/operstate)" = 'down' ]] && exit#------------------------------------------------------------------------ESSID=$(/sbin/iwconfig $INTERFACE | perl -n -e'/ESSID:"(.*?)"/ && print $1')#------------------------------------------------------------------------echo $ESSID # full textecho $ESSID # short text
#!/usr/bin/env python3# -*- coding: utf-8 -*-# Copyright © 2016 Anton Karmanov <bergentroll@openmailbox.org># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import configparserimport subprocessimport argparseimport imaplibfrom getpass import getpassimport ostry:import keyringkeyring_loaded = Trueexcept ImportError:keyring_loaded = False# _Settings____________________________________________________________________config = {'HOST': 'imap.mail_server.com','PORT': 993,'USER': 'my_mailbox@mail_server.com','PASS': '','URL': 'https://www.mail_server.com'}# _____________________________________________________________________________def get_args():parser = argparse.ArgumentParser(description='In interactive mode you able to manage your keys.')parser.add_argument('-a', '--add', type=str, help='add key to keyring')parser.add_argument('-r', '--remove', type=str, help='remove key from keyring')args = parser.parse_args()if args.add:match = Falsewhile not match:pass_1 = getpass('Type password : ')pass_2 = getpass('Type password again: ')if pass_1 == pass_2:match = Truekeyring.set_password('i3blocks-email', args.add, pass_1)else:print('\nPasswords do not match!\n')return(True)elif args.remove:ack = input('Are you sure want to delete key for {}? '.format(args.remove))if ack.lower() in ('y', 'yes'):keyring.delete_password('i3blocks-email', args.remove)else:print('Cancel.')return(True)return(False)def parse_instance():INSTANCE = ''try:INSTANCE = os.environ['BLOCK_INSTANCE']except KeyError:passfinally:if len(INSTANCE):parse_config(INSTANCE)def parse_config(INSTANCE):global configHOME = os.environ['HOME']config_file = configparser.ConfigParser()CONFIG_PATH = HOME + '/.config/i3blocks-email/' + INSTANCEconfig_file.read(CONFIG_PATH)for ITEM in config_file['MAIL']:ITEM = ITEM.upper()config[ITEM] = config_file['MAIL'][ITEM]def get_PASS():return(keyring.get_password('i3blocks-email', config['USER']))def block_event():try:event = os.environ['BLOCK_BUTTON']except KeyError:event = '0'if event == '1':NULL = open(os.devnull, 'w')subprocess.Popen(['xdg-open', config['URL']], stdout=NULL)def serf():box = imaplib.IMAP4_SSL(host=config['HOST'], port=config['PORT'])box.login(config['USER'], config['PASS'])box.select()result, ids = box.search(None, 'UNSEEN')box.logout()return(len(ids[0].split()))def printer(new_count):print(new_count)print(new_count)if new_count > 0:print('#00ff00')else:print('#ededed')if (keyring_loaded and not get_args()) or not keyring_loaded:parse_instance()block_event()if not config['PASS']:config['PASS'] = get_PASS()printer(serf())
#!/usr/bin/env python3# -*- coding: utf-8 -*-# Copyright © 2016 Anton Karmanov <bergentroll@openmailbox.org># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import configparserimport subprocessimport argparseimport imaplibfrom getpass import getpassimport ostry:import keyringkeyring_loaded = Trueexcept ImportError:keyring_loaded = False# _Settings____________________________________________________________________config = {'HOST': 'imap.mail_server.com','PORT': 993,'USER': 'my_mailbox@mail_server.com','PASS': '','URL': 'https://www.mail_server.com'}# _____________________________________________________________________________def get_args():parser = argparse.ArgumentParser(description='In interactive mode you able to manage your keys.')parser.add_argument('-a', '--add', type=str, help='add key to keyring')parser.add_argument('-r', '--remove', type=str, help='remove key from keyring')args = parser.parse_args()if args.add:match = Falsewhile not match:pass_1 = getpass('Type password : ')pass_2 = getpass('Type password again: ')if pass_1 == pass_2:match = Truekeyring.set_password('i3blocks-email', args.add, pass_1)else:print('\nPasswords do not match!\n')return(True)elif args.remove:ack = input('Are you sure want to delete key for {}? '.format(args.remove))if ack.lower() in ('y', 'yes'):keyring.delete_password('i3blocks-email', args.remove)else:print('Cancel.')return(True)return(False)def parse_instance():INSTANCE = ''try:INSTANCE = os.environ['BLOCK_INSTANCE']except KeyError:passfinally:if len(INSTANCE):parse_config(INSTANCE)def parse_config(INSTANCE):global configHOME = os.environ['HOME']config_file = configparser.ConfigParser()CONFIG_PATH = HOME + '/.config/i3blocks-email/' + INSTANCEconfig_file.read(CONFIG_PATH)for ITEM in config_file['MAIL']:ITEM = ITEM.upper()config[ITEM] = config_file['MAIL'][ITEM]def get_PASS():return(keyring.get_password('i3blocks-email', config['USER']))def block_event():try:event = os.environ['BLOCK_BUTTON']except KeyError:event = '0'if event == '1':NULL = open(os.devnull, 'w')subprocess.Popen(['xdg-open', config['URL']], stdout=NULL)def serf():box = imaplib.IMAP4_SSL(host=config['HOST'], port=config['PORT'])box.login(config['USER'], config['PASS'])box.select()result, ids = box.search(None, 'UNSEEN')box.logout()return(len(ids[0].split()))def printer(new_count):print(new_count)print(new_count)if new_count > 0:print('#00ff00')else:print('#ededed')if (keyring_loaded and not get_args()) or not keyring_loaded:parse_instance()block_event()if not config['PASS']:config['PASS'] = get_PASS()printer(serf())
#!/usr/bin/env python3"""A do-not-disturb button for muting Dunst notifications in i3 using i3blocksMute is handled using the `dunstctl` command."""__author__ = "Jessey White-Cinis <j@cin.is>"__copyright__ = "Copyright (c) 2019 Jessey White-Cinis"__license__ = "MIT"__version__ = "1.1.0"import osimport subprocess as spimport jsondef mute_toggle():'''Toggle dunst notifications'''sp.run(["dunstctl", "set-paused", "toggle"], check=True)def clicked():'''Returns True if the button was clicked'''button = os.environ.get("BLOCK_BUTTON", None)return bool(button)def muted():'''Returns True if Dunst is muted'''output = sp.check_output(('dunstctl', 'is-paused'))return u'true' == output.strip().decode("UTF-8")if clicked():# toggle button click to turn mute on and offmute_toggle()if muted():RTN = {"full_text":"<span font='Font Awesome 5 Free Solid' color='#BE616E'>\uf1f6</span>"}else:RTN = {"full_text":"<span font='Font Awesome 5 Free Solid' color='#A4B98E'>\uf0f3</span>"}print(json.dumps(RTN))
#!/usr/bin/env python3"""A do-not-disturb button for muting Dunst notifications in i3 using i3blocksMute is handled using the `dunstctl` command."""__author__ = "Jessey White-Cinis <j@cin.is>"__copyright__ = "Copyright (c) 2019 Jessey White-Cinis"__license__ = "MIT"__version__ = "1.1.0"import osimport subprocess as spimport jsondef mute_toggle():'''Toggle dunst notifications'''sp.run(["dunstctl", "set-paused", "toggle"], check=True)def clicked():'''Returns True if the button was clicked'''button = os.environ.get("BLOCK_BUTTON", None)return bool(button)def muted():'''Returns True if Dunst is muted'''output = sp.check_output(('dunstctl', 'is-paused'))return u'true' == output.strip().decode("UTF-8")if clicked():# toggle button click to turn mute on and offmute_toggle()if muted():RTN = {"full_text":"<span font='Font Awesome 5 Free Solid' color='#BE616E'>\uf1f6</span>"}else:RTN = {"full_text":"<span font='Font Awesome 5 Free Solid' color='#A4B98E'>\uf0f3</span>"}print(json.dumps(RTN))
#!/usr/bin/env bash# Number of docker containers runningcount=$(docker ps -q | wc -l | sed -r 's/^0$//g')# Recent docker container IPrecent_ip=$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" $(docker ps -ql))echo "$LABEL$count: $recent_ip"
#!/usr/bin/env bash# Number of docker containers runningcount=$(docker ps -q | wc -l | sed -r 's/^0$//g')# Recent docker container IPrecent_ip=$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" $(docker ps -ql))echo "$LABEL$count: $recent_ip"
#!/usr/bin/python# -*- coding: utf-8 -*-# MIT License# Copyright (c) 2017 Christian Schläppi# Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to deal# in the Software without restriction, including without limitation the rights# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:# The above copyright notice and this permission notice shall be included in all# copies or substantial portions of the Software.# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE# SOFTWARE.import osimport sysimport subprocessdef get_disk_stats(mp):stat = os.statvfs(mp)total = stat.f_blocks * stat.f_frsize / 1024 ** 3avail = stat.f_bavail * stat.f_frsize / 1024 ** 3used = total - availreturn {'avail': avail,'total': total,'used': used,'perc_used': 100 * used / total}def launch_ncdu(mp):cmd = ['/usr/bin/sakura','-t','pop-up','-e','/usr/bin/ncdu %s' % mp,'-x',]subprocess.Popen(cmd,stdout=open(os.devnull, 'w'),stderr=subprocess.STDOUT)def parse_args():args = {'warn_threshold': 80,'crit_threshold': 90,'warn_color': '#d6af4e','crit_color': '#d64e4e','format': '{used:.1f}G/{total:.1f}G ({perc_used:.1f}%) - {avail:.1f}G'}try:for arg in sys.argv[1:]:key, value = arg.split('=')args[key] = int(value) if value.isdigit() else valueexcept (KeyError, ValueError):# ValuError in case user does something weirdpassreturn argsdef get_instance():p = os.getenv('BLOCK_INSTANCE')if p and os.path.exists(p):return preturn os.getenv('HOME')def main():output_color = ''args = parse_args()m_point = get_instance()stats = get_disk_stats(m_point)# get some more info when not called by i3blocksif not os.getenv('BLOCK_NAME'):print('Args: %s' % args)print('Stats: %s' % stats)print('Mount Point: %s' % m_point)# print stats with format if givenprint(args['format'].format(**stats))print()# determine colorif args['crit_threshold'] > int(stats['perc_used']) >= args['warn_threshold']:output_color = args['warn_color']elif stats['perc_used'] >= args['crit_threshold']:output_color = args['crit_color']print(output_color)# handle click-event_button = os.getenv('BLOCK_BUTTON')if _button and int(_button) == 1:launch_ncdu(m_point)if __name__ == '__main__':main()
#!/usr/bin/python# -*- coding: utf-8 -*-# MIT License# Copyright (c) 2017 Christian Schläppi# Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to deal# in the Software without restriction, including without limitation the rights# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:# The above copyright notice and this permission notice shall be included in all# copies or substantial portions of the Software.# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE# SOFTWARE.import osimport sysimport subprocessdef get_disk_stats(mp):stat = os.statvfs(mp)total = stat.f_blocks * stat.f_frsize / 1024 ** 3avail = stat.f_bavail * stat.f_frsize / 1024 ** 3used = total - availreturn {'avail': avail,'total': total,'used': used,'perc_used': 100 * used / total}def launch_ncdu(mp):cmd = ['/usr/bin/sakura','-t','pop-up','-e','/usr/bin/ncdu %s' % mp,'-x',]subprocess.Popen(cmd,stdout=open(os.devnull, 'w'),stderr=subprocess.STDOUT)def parse_args():args = {'warn_threshold': 80,'crit_threshold': 90,'warn_color': '#d6af4e','crit_color': '#d64e4e','format': '{used:.1f}G/{total:.1f}G ({perc_used:.1f}%) - {avail:.1f}G'}try:for arg in sys.argv[1:]:key, value = arg.split('=')args[key] = int(value) if value.isdigit() else valueexcept (KeyError, ValueError):# ValuError in case user does something weirdpassreturn argsdef get_instance():p = os.getenv('BLOCK_INSTANCE')if p and os.path.exists(p):return preturn os.getenv('HOME')def main():output_color = ''args = parse_args()m_point = get_instance()stats = get_disk_stats(m_point)# get some more info when not called by i3blocksif not os.getenv('BLOCK_NAME'):print('Args: %s' % args)print('Stats: %s' % stats)print('Mount Point: %s' % m_point)# print stats with format if givenprint(args['format'].format(**stats))print()# determine colorif args['crit_threshold'] > int(stats['perc_used']) >= args['warn_threshold']:output_color = args['warn_color']elif stats['perc_used'] >= args['crit_threshold']:output_color = args['crit_color']print(output_color)# handle click-event_button = os.getenv('BLOCK_BUTTON')if _button and int(_button) == 1:launch_ncdu(m_point)if __name__ == '__main__':main()
#!/usr/bin/env bash## Copyright (C) 2016 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to monitor disk iolabel="${LABEL:-""}"dt="${DT:-5}"MB_only="${MB_ONLY:-0}"kB_only="${KB_ONLY:-0}"width="${WIDTH:-4}"MB_precision="${MB_PRECISION:-1}"kB_precision="${KB_PRECISION:-0}"regex="${REGEX:-$BLOCK_INSTANCE}"regex="${regex:-/^(s|h)d[a-zA-Z]+/}"threshold="${THRESHOLD:-0}"warn_color="${WARN_COLOR:-#FF0000}"sep="${SEPARATOR:-/}"unit_suffix="${SUFFIX:-B/s}"align="${ALIGN--}"function list_devices {echo "Devices iostat reports that match our regex:"iostat | awk '$1~/^(s|h)d[a-zA-Z]+/{print $1}'}while getopts L:t:w:p:P:R:s:ST:C:lLMmKkh opt; docase "$opt" inL) label="$OPTARG" ;;t) dt="$OPTARG" ;;w) width="$OPTARG" ;;p) kB_precision="$OPTARG" ;;P) MB_precision="$OPTARG" ;;R) regex="$OPTARG" ;;s) sep="$OPTARG" ;;S) unit_suffix="" ;;T) threshold="$OPTARG" ;;C) warn_color="$OPTARG" ;;l) list_devices; exit 0 ;;M|m) MB_only=1 ;;K|k) kB_only=1 ;;h) printf \"Usage: disk-io [-t time] [-w width] [-p kB_precision] [-P MB_precision] [-R regex] [-s separator] [-S] [-T threshold [-C warn_color]] [-k|-M] [-l] [-h]Options:-L\tLabel to put in front of the text. Default: $label-t\tTime interval in seconds between measurements. Default: $dt-w\tThe width of printed floats. Default: $width-p\tThe precision of kB/s floats. Default: $kB_precision-P\tThe precision of MB/s floats. Default: $MB_precision-R\tRegex that devices must match. Default: $regex-s\tSeparator to put between rates. Default: $sep-S\tShort units, omit B/s in kB/s and MB/s.-T\tRate in kB/s to exceed to trigger a warning. Default: not enabled-C\tColor to change the blocklet to warn the user. Default: $warn_color-l\tList devices that iostat reports-M\tDo not switch between MB/s and kB/s, use only MB/s-k\tDo not switch between MB/s and kB/s, use only kB/s-h\tShow this help text" && exit 0;;esacdoneiostat -dyz "$dt" | awk -v sep="$sep" "BEGIN {rx = wx = 0;}{if(\$0 == \"\") {if ($threshold > 0 && (rx >= $threshold || wx >= $threshold)) {printf \"<span color='$warn_color'>\";}printf \"$label\";if(!$kB_only && ($MB_only || rx >= 1024 || wx >= 1024)) {printf \"%$align$width.${MB_precision}f%s%$width.${MB_precision}f M$unit_suffix\", rx/1024, sep, wx/1024;}else {printf \"%$align$width.${kB_precision}f%s%$width.${kB_precision}f k$unit_suffix\", rx, sep, wx;}if ($threshold > 0 && (rx >= $threshold || wx >= $threshold)) {printf \"</span>\";}printf \"\n\";fflush(stdout);}else if(\$1~/^Device:?/) {rx = wx = 0;}else if(\$1~$regex) {rx += \$3;wx += \$4;}}"
#!/usr/bin/env bash## Copyright (C) 2016 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to monitor disk iolabel="${LABEL:-""}"dt="${DT:-5}"MB_only="${MB_ONLY:-0}"kB_only="${KB_ONLY:-0}"width="${WIDTH:-4}"MB_precision="${MB_PRECISION:-1}"kB_precision="${KB_PRECISION:-0}"regex="${REGEX:-$BLOCK_INSTANCE}"regex="${regex:-/^(s|h)d[a-zA-Z]+/}"threshold="${THRESHOLD:-0}"warn_color="${WARN_COLOR:-#FF0000}"sep="${SEPARATOR:-/}"unit_suffix="${SUFFIX:-B/s}"align="${ALIGN--}"function list_devices {echo "Devices iostat reports that match our regex:"iostat | awk '$1~/^(s|h)d[a-zA-Z]+/{print $1}'}while getopts L:t:w:p:P:R:s:ST:C:lLMmKkh opt; docase "$opt" inL) label="$OPTARG" ;;t) dt="$OPTARG" ;;w) width="$OPTARG" ;;p) kB_precision="$OPTARG" ;;P) MB_precision="$OPTARG" ;;R) regex="$OPTARG" ;;s) sep="$OPTARG" ;;S) unit_suffix="" ;;T) threshold="$OPTARG" ;;C) warn_color="$OPTARG" ;;l) list_devices; exit 0 ;;M|m) MB_only=1 ;;K|k) kB_only=1 ;;h) printf \"Usage: disk-io [-t time] [-w width] [-p kB_precision] [-P MB_precision] [-R regex] [-s separator] [-S] [-T threshold [-C warn_color]] [-k|-M] [-l] [-h]Options:-L\tLabel to put in front of the text. Default: $label-t\tTime interval in seconds between measurements. Default: $dt-w\tThe width of printed floats. Default: $width-p\tThe precision of kB/s floats. Default: $kB_precision-P\tThe precision of MB/s floats. Default: $MB_precision-R\tRegex that devices must match. Default: $regex-s\tSeparator to put between rates. Default: $sep-S\tShort units, omit B/s in kB/s and MB/s.-T\tRate in kB/s to exceed to trigger a warning. Default: not enabled-C\tColor to change the blocklet to warn the user. Default: $warn_color-l\tList devices that iostat reports-M\tDo not switch between MB/s and kB/s, use only MB/s-k\tDo not switch between MB/s and kB/s, use only kB/s-h\tShow this help text" && exit 0;;esacdoneiostat -dyz "$dt" | awk -v sep="$sep" "BEGIN {rx = wx = 0;}{if(\$0 == \"\") {if ($threshold > 0 && (rx >= $threshold || wx >= $threshold)) {printf \"<span color='$warn_color'>\";}printf \"$label\";if(!$kB_only && ($MB_only || rx >= 1024 || wx >= 1024)) {printf \"%$align$width.${MB_precision}f%s%$width.${MB_precision}f M$unit_suffix\", rx/1024, sep, wx/1024;}else {printf \"%$align$width.${kB_precision}f%s%$width.${kB_precision}f k$unit_suffix\", rx, sep, wx;}if ($threshold > 0 && (rx >= $threshold || wx >= $threshold)) {printf \"</span>\";}printf \"\n\";fflush(stdout);}else if(\$1~/^Device:?/) {rx = wx = 0;}else if(\$1~$regex) {rx += \$3;wx += \$4;}}"
#!/usr/bin/env sh# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.DIR="${DIR:-$BLOCK_INSTANCE}"DIR="${DIR:-$HOME}"ALERT_LOW="${ALERT_LOW:-$1}"ALERT_LOW="${ALERT_LOW:-10}" # color will turn red under this value (default: 10%)LOCAL_FLAG="-l"if [ "$1" = "-n" ] || [ "$2" = "-n" ]; thenLOCAL_FLAG=""fidf -h -P $LOCAL_FLAG "$DIR" | awk -v label="$LABEL" -v alert_low=$ALERT_LOW '/\/.*/ {# full textprint label $4# short textprint label $4use=$5# no need to continue parsingexit 0}END {gsub(/%$/,"",use)if (100 - use < alert_low) {# colorprint "#FF0000"}}'
#!/usr/bin/env sh# Copyright (C) 2014 Julien Bonjean <julien@bonjean.info># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.DIR="${DIR:-$BLOCK_INSTANCE}"DIR="${DIR:-$HOME}"ALERT_LOW="${ALERT_LOW:-$1}"ALERT_LOW="${ALERT_LOW:-10}" # color will turn red under this value (default: 10%)LOCAL_FLAG="-l"if [ "$1" = "-n" ] || [ "$2" = "-n" ]; thenLOCAL_FLAG=""fidf -h -P $LOCAL_FLAG "$DIR" | awk -v label="$LABEL" -v alert_low=$ALERT_LOW '/\/.*/ {# full textprint label $4# short textprint label $4use=$5# no need to continue parsingexit 0}END {gsub(/%$/,"",use)if (100 - use < alert_low) {# colorprint "#FF0000"}}'
#!/usr/bin/env bash# dimmer is a script that changes hex color codes to reduce brightness# Copyright (C) 2016 Anton Karmanov <starcom24@gmail.com>## This program 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 any# later version.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.brightness=50if [ -n "$1" ] ; thenbrightness=$1fishopt -s nocasematchwhile read -r linedoif! [[ $brightness =~ ^[0-9]+$ ]] || \[ "$brightness" -lt 0 ] || \[ "$brightness" -gt 100 ]then>&2 echo "dimmer: Invalid brightness value"exit 1fiif [ ${#line} -eq 7 ] && [ "${line:0:1}" = "#" ] &&\[[ ${line:1:6} =~ ^[0-9A-F]{6}$ ]]thenif [ "${brightness}" -eq 0 ]then# shellcheck disable=SC2016line='$000000'elsecolors=("0x${line:1:2}" "0x${line:3:2}" "0x${line:5:2}")line='#'for color in "${colors[@]}"; dovalue=$(((color + (100 / brightness - 1)) * brightness / 100))color=$(echo "obase=16; ${value}" | bc)# If <= 9 supplement with 0.if [ ${#color} -lt 2 ] ; thencolor="0${color}"filine="$line$color"donefifiecho "$line"done
#!/usr/bin/env bash# dimmer is a script that changes hex color codes to reduce brightness# Copyright (C) 2016 Anton Karmanov <starcom24@gmail.com>## This program 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 any# later version.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.brightness=50if [ -n "$1" ] ; thenbrightness=$1fishopt -s nocasematchwhile read -r linedoif! [[ $brightness =~ ^[0-9]+$ ]] || \[ "$brightness" -lt 0 ] || \[ "$brightness" -gt 100 ]then>&2 echo "dimmer: Invalid brightness value"exit 1fiif [ ${#line} -eq 7 ] && [ "${line:0:1}" = "#" ] &&\[[ ${line:1:6} =~ ^[0-9A-F]{6}$ ]]thenif [ "${brightness}" -eq 0 ]then# shellcheck disable=SC2016line='$000000'elsecolors=("0x${line:1:2}" "0x${line:3:2}" "0x${line:5:2}")line='#'for color in "${colors[@]}"; dovalue=$(((color + (100 / brightness - 1)) * brightness / 100))color=$(echo "obase=16; ${value}" | bc)# If <= 9 supplement with 0.if [ ${#color} -lt 2 ] ; thencolor="0${color}"filine="$line$color"donefifiecho "$line"done
#!/usr/bin/env bash# cpu_util_detailed# Meant for usage as an i3blocks blocklet.# It reports detailed CPU utilization in colors using pango markup.# Written by skidnik <skidnik@gmail.com># Licensed under GPLv3 https://www.gnu.org/licenses/gpl-3.0.txt## Defaults if not setinterval=${interval:-0} # just in case it's started not by i3blocksstats=${stats:-usr nice sys iowait}format=${format:-%6.2f}warn=${warn:-80}declare -A colormap=([usr]=${usr_color:-green}[nice]=${nice_color:-yellow}[sys]=${sys_color:-red}[iowait]=${iowait_color:-grey}[irq]=${irq_color:-purple}[soft]=${soft_color:-violet}[steal]=${steal_color:-orange}[guest]=${guest_color:-cyan}[gnice]=${gnice_color:-blue}[idle]=${idle_color:-white}[total]=${total_color:-white})# If $report_time not set:# Set it to $interval - 1, but not less than 1.# If $interval is 'repeat' or -2 set report_time to 5.if [[ -z $report_time ]]; thenif [[ "$interval" =~ ^-?[0-9]+$ ]];thenif [[ $interval -gt 2 ]]; thenreport_time=$(( interval - 1 ))elif [[ $interval == -2 ]]; thenreport_time=5elsereport_time=1fielif [[ $interval == repeat ]]; thenreport_time=5fifi# 'idle' is hardcoded as it's always required, no need to ask for it two times.getstats=${stats//idle /}# Get detailed CPU load as a set of variables with same names:if _mpstat="$(command -v mpstat)"thendeclare $( ${_mpstat} -u "$report_time" 1 | sed -n '3,4p' | awk -v stats="$getstats idle" 'BEGIN{split(stats, fields)}{split($0, headers)getlinesplit($0, values)for (i in fields) {for (j in headers)if ( headers[j] ~ "^%" fields[i] ) {printf "%s=%s\n", fields[i], values[j]}}}')total=$( bc <<<"scale=2; 100 - $idle" )else# This is a fallback way for the case `mpstat` is not availablestart_uptime=($(cat /proc/uptime))start=($(sed -n '1p' /proc/stat))sleep ${report_time}end_uptime=($(cat /proc/uptime))end=($(sed -n '1p' /proc/stat))user_hz=$(getconf CLK_TCK)num_cpus=$(nproc --all)delta_time=$( bc <<<"scale=2; ${end_uptime[0]}-${start_uptime[0]}" )user_hz_time=$( bc <<<"$delta_time * $user_hz" )usr=$( bc <<<"scale=4; (${end[1]}-${start[1]})/$num_cpus/$user_hz_time*100" )nice=$( bc <<<"scale=4; (${end[2]}-${start[2]})/$num_cpus/$user_hz_time*100" )sys=$( bc <<<"scale=4; (${end[3]}-${start[3]})/$num_cpus/$user_hz_time*100" )idle=$( bc <<<"scale=4; (${end[4]}-${start[4]})/$num_cpus/$user_hz_time*100" )iowait=$( bc <<<"scale=4; (${end[5]}-${start[5]})/$num_cpus/$user_hz_time*100" )irq=$( bc <<<"scale=4; (${end[6]}-${start[6]})/$num_cpus/$user_hz_time*100" )soft=$( bc <<<"scale=4; (${end[7]}-${start[7]})/$num_cpus/$user_hz_time*100" )steal=$( bc <<<"scale=4; (${end[8]}-${start[8]})/$num_cpus/$user_hz_time*100" )guest=$( bc <<<"scale=4; (${end[9]}-${start[9]})/$num_cpus/$user_hz_time*100" )gnice=$( bc <<<"scale=4; (${end[10]}-${start[10]})/$num_cpus/$user_hz_time*100" )total=$( bc <<<"scale=4; ${end_uptime[1]}-${start_uptime[1]}" )fi# Output stats with pango formatting in a defined orderfor stat in $statsdo# No other way to make format adjustable# shellcheck disable=SC2059printf "<span color='%s'>$format</span>" "${colormap[$stat]}" "${!stat}"doneecho # trailing newline# Short text# shellcheck disable=SC2059printf "$format\n" "$total"# Set urgent flag if over warn threshold(( $( bc <<<"$total >= $warn" ) )) && exit 33 || :
#!/usr/bin/env bash# cpu_util_detailed# Meant for usage as an i3blocks blocklet.# It reports detailed CPU utilization in colors using pango markup.# Written by skidnik <skidnik@gmail.com># Licensed under GPLv3 https://www.gnu.org/licenses/gpl-3.0.txt## Defaults if not setinterval=${interval:-0} # just in case it's started not by i3blocksstats=${stats:-usr nice sys iowait}format=${format:-%6.2f}warn=${warn:-80}declare -A colormap=([usr]=${usr_color:-green}[nice]=${nice_color:-yellow}[sys]=${sys_color:-red}[iowait]=${iowait_color:-grey}[irq]=${irq_color:-purple}[soft]=${soft_color:-violet}[steal]=${steal_color:-orange}[guest]=${guest_color:-cyan}[gnice]=${gnice_color:-blue}[idle]=${idle_color:-white}[total]=${total_color:-white})# If $report_time not set:# Set it to $interval - 1, but not less than 1.# If $interval is 'repeat' or -2 set report_time to 5.if [[ -z $report_time ]]; thenif [[ "$interval" =~ ^-?[0-9]+$ ]];thenif [[ $interval -gt 2 ]]; thenreport_time=$(( interval - 1 ))elif [[ $interval == -2 ]]; thenreport_time=5elsereport_time=1fielif [[ $interval == repeat ]]; thenreport_time=5fifi# 'idle' is hardcoded as it's always required, no need to ask for it two times.getstats=${stats//idle /}# Get detailed CPU load as a set of variables with same names:if _mpstat="$(command -v mpstat)"thendeclare $( ${_mpstat} -u "$report_time" 1 | sed -n '3,4p' | awk -v stats="$getstats idle" 'BEGIN{split(stats, fields)}{split($0, headers)getlinesplit($0, values)for (i in fields) {for (j in headers)if ( headers[j] ~ "^%" fields[i] ) {printf "%s=%s\n", fields[i], values[j]}}}')total=$( bc <<<"scale=2; 100 - $idle" )else# This is a fallback way for the case `mpstat` is not availablestart_uptime=($(cat /proc/uptime))start=($(sed -n '1p' /proc/stat))sleep ${report_time}end_uptime=($(cat /proc/uptime))end=($(sed -n '1p' /proc/stat))user_hz=$(getconf CLK_TCK)num_cpus=$(nproc --all)delta_time=$( bc <<<"scale=2; ${end_uptime[0]}-${start_uptime[0]}" )user_hz_time=$( bc <<<"$delta_time * $user_hz" )usr=$( bc <<<"scale=4; (${end[1]}-${start[1]})/$num_cpus/$user_hz_time*100" )nice=$( bc <<<"scale=4; (${end[2]}-${start[2]})/$num_cpus/$user_hz_time*100" )sys=$( bc <<<"scale=4; (${end[3]}-${start[3]})/$num_cpus/$user_hz_time*100" )idle=$( bc <<<"scale=4; (${end[4]}-${start[4]})/$num_cpus/$user_hz_time*100" )iowait=$( bc <<<"scale=4; (${end[5]}-${start[5]})/$num_cpus/$user_hz_time*100" )irq=$( bc <<<"scale=4; (${end[6]}-${start[6]})/$num_cpus/$user_hz_time*100" )soft=$( bc <<<"scale=4; (${end[7]}-${start[7]})/$num_cpus/$user_hz_time*100" )steal=$( bc <<<"scale=4; (${end[8]}-${start[8]})/$num_cpus/$user_hz_time*100" )guest=$( bc <<<"scale=4; (${end[9]}-${start[9]})/$num_cpus/$user_hz_time*100" )gnice=$( bc <<<"scale=4; (${end[10]}-${start[10]})/$num_cpus/$user_hz_time*100" )total=$( bc <<<"scale=4; ${end_uptime[1]}-${start_uptime[1]}" )fi# Output stats with pango formatting in a defined orderfor stat in $statsdo# No other way to make format adjustable# shellcheck disable=SC2059printf "<span color='%s'>$format</span>" "${colormap[$stat]}" "${!stat}"doneecho # trailing newline# Short text# shellcheck disable=SC2059printf "$format\n" "$total"# Set urgent flag if over warn threshold(( $( bc <<<"$total >= $warn" ) )) && exit 33 || :
#!/usr/bin/env perl## Copyright 2014 Pierre Mavro <deimos@deimos.fr># Copyright 2014 Vivien Didelot <vivien@didelot.org># Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com>## Licensed under the terms of the GNU GPL v3, or any later version.use strict;use warnings;use utf8;use Getopt::Long;# default valuesmy $t_warn = $ENV{T_WARN} // 50;my $t_crit = $ENV{T_CRIT} // 80;my $cpu_usage = -1;my $decimals = 0;my $label = $ENV{LABEL} // "";my $color_normal = $ENV{COLOR_NORMAL} // "#EBDBB2";my $color_warn = $ENV{COLOR_WARN} // "#FFFC00";my $color_crit = $ENV{COLOR_CRIT} // "#FF0000";sub help {print "Usage: cpu_usage [-w <warning>] [-c <critical>] [-d <decimals>]\n";print "-w <percent>: warning threshold to become yellow\n";print "-c <percent>: critical threshold to become red\n";print "-d <decimals>: Use <decimals> decimals for percentage (default is $decimals) \n";exit 0;}GetOptions("help|h" => \&help,"w=i" => \$t_warn,"c=i" => \$t_crit,"d=i" => \$decimals,);# Get CPU usage$ENV{LC_ALL}="en_US"; # if mpstat is not run under en_US locale, things may break, so make sure it isopen (MPSTAT, 'mpstat 1 1 |') or die;while (<MPSTAT>) {if (/^.*\s+(\d+\.\d+)[\s\x00]?$/) {$cpu_usage = 100 - $1; # 100% - %idlelast;}}close(MPSTAT);$cpu_usage eq -1 and die 'Can\'t find CPU information';# Print short_text, full_textprint "${label}";printf "%.${decimals}f%%\n", $cpu_usage;print "${label}";printf "%.${decimals}f%%\n", $cpu_usage;# Print color, if neededif ($cpu_usage >= $t_crit) {print "${color_crit}\n";} elsif ($cpu_usage >= $t_warn) {print "${color_warn}\n";} else {print "${color_normal}\n";}exit 0;
#!/usr/bin/env perl## Copyright 2014 Pierre Mavro <deimos@deimos.fr># Copyright 2014 Vivien Didelot <vivien@didelot.org># Copyright 2014 Andreas Guldstrand <andreas.guldstrand@gmail.com>## Licensed under the terms of the GNU GPL v3, or any later version.use strict;use warnings;use utf8;use Getopt::Long;# default valuesmy $t_warn = $ENV{T_WARN} // 50;my $t_crit = $ENV{T_CRIT} // 80;my $cpu_usage = -1;my $decimals = 0;my $label = $ENV{LABEL} // "";my $color_normal = $ENV{COLOR_NORMAL} // "#EBDBB2";my $color_warn = $ENV{COLOR_WARN} // "#FFFC00";my $color_crit = $ENV{COLOR_CRIT} // "#FF0000";sub help {print "Usage: cpu_usage [-w <warning>] [-c <critical>] [-d <decimals>]\n";print "-w <percent>: warning threshold to become yellow\n";print "-c <percent>: critical threshold to become red\n";print "-d <decimals>: Use <decimals> decimals for percentage (default is $decimals) \n";exit 0;}GetOptions("help|h" => \&help,"w=i" => \$t_warn,"c=i" => \$t_crit,"d=i" => \$decimals,);# Get CPU usage$ENV{LC_ALL}="en_US"; # if mpstat is not run under en_US locale, things may break, so make sure it isopen (MPSTAT, 'mpstat 1 1 |') or die;while (<MPSTAT>) {if (/^.*\s+(\d+\.\d+)[\s\x00]?$/) {$cpu_usage = 100 - $1; # 100% - %idlelast;}}close(MPSTAT);$cpu_usage eq -1 and die 'Can\'t find CPU information';# Print short_text, full_textprint "${label}";printf "%.${decimals}f%%\n", $cpu_usage;print "${label}";printf "%.${decimals}f%%\n", $cpu_usage;# Print color, if neededif ($cpu_usage >= $t_crit) {print "${color_crit}\n";} elsif ($cpu_usage >= $t_warn) {print "${color_warn}\n";} else {print "${color_normal}\n";}exit 0;
#!/usr/bin/env bashUSAGE=$( vmstat 1 2 | tail -1 | awk '{usage=100 - $15} END {print usage}')# Define colors based on signal strengthif [[ -z "$USAGE" ]]; thenCOLOR="#EBDBB2"elseif [ "$USAGE" -ge 90 ]; thenCOLOR="#FF6600"elif [ "$USAGE" -ge 80 ]; thenCOLOR="#FF9900"elif [ "$USAGE" -ge 60 ]; thenCOLOR="#FFDBA0"elif [ "$USAGE" -ge 40 ]; thenCOLOR="#FFDBA0"elif [ "$USAGE" -ge 20 ]; thenCOLOR="#EBDBB2"elseCOLOR="#EBDBB2"fifi# Print the output with colorecho "<span color='$COLOR'><> $USAGE%</span>"
#!/usr/bin/env bashUSAGE=$( vmstat 1 2 | tail -1 | awk '{usage=100 - $15} END {print usage}')# Define colors based on signal strengthif [[ -z "$USAGE" ]]; thenCOLOR="#EBDBB2"elseif [ "$USAGE" -ge 90 ]; thenCOLOR="#FF6600"elif [ "$USAGE" -ge 80 ]; thenCOLOR="#FF9900"elif [ "$USAGE" -ge 60 ]; thenCOLOR="#FFDBA0"elif [ "$USAGE" -ge 40 ]; thenCOLOR="#FFDBA0"elif [ "$USAGE" -ge 20 ]; thenCOLOR="#EBDBB2"elseCOLOR="#EBDBB2"fifi# Print the output with colorecho "<span color='$COLOR'><> $USAGE%</span>"
#!/bin/shset -exPREFIX=$(echo $1 | cut -d= -f 2)if [ -n "$PREFIX" ]thensed -i "s;^PREFIX.*;PREFIX = $PREFIX;g" Makefilefi
#!/usr/bin/env bash###### Default environment variables ######IDLE_TEXT=${IDLE_TEXT:-CPICK}IDLE_TEXT_COLOR=${IDLE_TEXT_COLOR:-#FFFFFF}###### Verify dependencies ######if ! command -v xdotool &> /dev/null || ! command -v grabc &> /dev/null; thenerror 'xdotool and/or grabc is not available'exit 1fi###### Functions ######error() {echo Error: "$@" 1>&2}play_pause() {$running && pause || play}play() {running=truepickcolor}pause() {running=falsefgcolor="$IDLE_TEXT_COLOR"}hash2hex() {echo "${1/\#/0x}"}subtract_colors() {col1=$(hash2hex "$1")col2=$(hash2hex "$2")b1=$(( col1 % 0x000100 ))g1=$(( (col1 % 0x010000 - b1) / 0x100 ))r1=$(( (col1 % 0x1000000 - 0x100*g1 - b1) / 0x10000 ))b2=$(( col2 % 0x000100 ))g2=$(( (col2 % 0x010000 - b2) / 0x100 ))r2=$(( (col2 % 0x1000000 - 0x100*g2 - b2) / 0x10000 ))dr=$(( r2 - r1 ))dg=$(( g2 - g1 ))db=$(( b2 - b1 ))echo $(( ${dr#-} + ${dg#-} + ${db#-} ))}rgbcmybw=([0]='#ff0000'[1]='#00ff00'[2]='#0000ff'[3]='#ffff00'[4]='#ff00ff'[5]='#00ffff'[6]='#000000'[7]='#ffffff')pickcolor() {> /dev/null 2>&1 xdotool sleep 0.01 click 1 &bgcolor=$(grabc 2> /dev/null)col_diff_max=0col_diff=0for col in "${rgbcmybw[@]}"; docol_diff=$(subtract_colors "$col" "$bgcolor")if (( ${col_diff#-} > "$col_diff_max" )); thenfgcolor=$colcol_diff_max=${col_diff#-}fidone}###### Initialize ######[[ ! -v running ]] && pause###### Click processing ######case $BLOCK_BUTTON in1 )play_pause;;esac###### Update color ######if $running; thenpickcolorbgcolorstring='"background":"'"$bgcolor"'"'elsebgcolor="$IDLE_TEXT"bgcolorstring=fi###### Output ######cat << EOF{"full_text":"$bgcolor",\"running":"$running",\"bgcolor":"$bgcolor",\"fgcolor":"$fgcolor",\"color":"$fgcolor",\$bgcolorstring\}EOF
#!/usr/bin/env bash###### Default environment variables ######IDLE_TEXT=${IDLE_TEXT:-CPICK}IDLE_TEXT_COLOR=${IDLE_TEXT_COLOR:-#FFFFFF}###### Verify dependencies ######if ! command -v xdotool &> /dev/null || ! command -v grabc &> /dev/null; thenerror 'xdotool and/or grabc is not available'exit 1fi###### Functions ######error() {echo Error: "$@" 1>&2}play_pause() {$running && pause || play}play() {running=truepickcolor}pause() {running=falsefgcolor="$IDLE_TEXT_COLOR"}hash2hex() {echo "${1/\#/0x}"}subtract_colors() {col1=$(hash2hex "$1")col2=$(hash2hex "$2")b1=$(( col1 % 0x000100 ))g1=$(( (col1 % 0x010000 - b1) / 0x100 ))r1=$(( (col1 % 0x1000000 - 0x100*g1 - b1) / 0x10000 ))b2=$(( col2 % 0x000100 ))g2=$(( (col2 % 0x010000 - b2) / 0x100 ))r2=$(( (col2 % 0x1000000 - 0x100*g2 - b2) / 0x10000 ))dr=$(( r2 - r1 ))dg=$(( g2 - g1 ))db=$(( b2 - b1 ))echo $(( ${dr#-} + ${dg#-} + ${db#-} ))}rgbcmybw=([0]='#ff0000'[1]='#00ff00'[2]='#0000ff'[3]='#ffff00'[4]='#ff00ff'[5]='#00ffff'[6]='#000000'[7]='#ffffff')pickcolor() {> /dev/null 2>&1 xdotool sleep 0.01 click 1 &bgcolor=$(grabc 2> /dev/null)col_diff_max=0col_diff=0for col in "${rgbcmybw[@]}"; docol_diff=$(subtract_colors "$col" "$bgcolor")if (( ${col_diff#-} > "$col_diff_max" )); thenfgcolor=$colcol_diff_max=${col_diff#-}fidone}###### Initialize ######[[ ! -v running ]] && pause###### Click processing ######case $BLOCK_BUTTON in1 )play_pause;;esac###### Update color ######if $running; thenpickcolorbgcolorstring='"background":"'"$bgcolor"'"'elsebgcolor="$IDLE_TEXT"bgcolorstring=fi###### Output ######cat << EOF{"full_text":"$bgcolor",\"running":"$running",\"bgcolor":"$bgcolor",\"fgcolor":"$fgcolor",\"color":"$fgcolor",\$bgcolorstring\}EOF
#!/usr/bin/env shWIDTH=${WIDTH:-200}HEIGHT=${HEIGHT:-200}DATEFMT=${DATEFMT:-"+%a %d.%m.%Y %H:%M:%S"}SHORTFMT=${SHORTFMT:-"+%H:%M:%S"}OPTIND=1while getopts ":f:W:H:" opt; docase $opt inf) DATEFMT="$OPTARG" ;;W) WIDTH="$OPTARG" ;;H) HEIGHT="$OPTARG" ;;\?)echo "Invalid option: -$OPTARG" >&2exit 1;;:)echo "Option -$OPTARG requires an argument." >&2exit 1;;esacdonecase "$BLOCK_BUTTON" in1|2|3)# the position of the upper left corner of the popupposX=$(($BLOCK_X - $WIDTH / 2))posY=$(($BLOCK_Y - $HEIGHT))i3-msg -q "exec yad --calendar \--width=$WIDTH --height=$HEIGHT \--undecorated --fixed \--close-on-unfocus --no-buttons \--posx=$posX --posy=$posY \> /dev/null"esacecho "$LABEL$(date "$DATEFMT")"echo "$LABEL$(date "$SHORTFMT")"
#!/usr/bin/env shWIDTH=${WIDTH:-200}HEIGHT=${HEIGHT:-200}DATEFMT=${DATEFMT:-"+%a %d.%m.%Y %H:%M:%S"}SHORTFMT=${SHORTFMT:-"+%H:%M:%S"}OPTIND=1while getopts ":f:W:H:" opt; docase $opt inf) DATEFMT="$OPTARG" ;;W) WIDTH="$OPTARG" ;;H) HEIGHT="$OPTARG" ;;\?)echo "Invalid option: -$OPTARG" >&2exit 1;;:)echo "Option -$OPTARG requires an argument." >&2exit 1;;esacdonecase "$BLOCK_BUTTON" in1|2|3)# the position of the upper left corner of the popupposX=$(($BLOCK_X - $WIDTH / 2))posY=$(($BLOCK_Y - $HEIGHT))i3-msg -q "exec yad --calendar \--width=$WIDTH --height=$HEIGHT \--undecorated --fixed \--close-on-unfocus --no-buttons \--posx=$posX --posy=$posY \> /dev/null"esacecho "$LABEL$(date "$DATEFMT")"echo "$LABEL$(date "$SHORTFMT")"
#!/bin/bashECHO=""COLOR="#999999"BLUETOOTHCTL=$(which bluetoothctl)# Check if bluetoothctl existsif [ ! -x "$BLUETOOTHCTL" ]; thenECHO="X"# Check if Bluetooth is powered onelseif ! bluetoothctl show | grep -q "Powered: yes"; thenECHO="x"else# Function to get all available devices (both paired and unpaired)get_available_devices() {$BLUETOOTHCTL devices | awk '{$1=$2=""; print $0}' | xargs}# Function to get all paired devicesget_paired_devices() {$BLUETOOTHCTL devices Paired | awk '{$1=$2=""; print $0}' | xargs}# Function to get connected devicesget_connected_devices() {$BLUETOOTHCTL devices Connected | awk '{$1=$2=""; print $0}' | xargs}# List paired devicesCONNECTED_DEVICES=$(get_connected_devices)# Count connected devicesCONNECTED_COUNT=$(echo "$CONNECTED_DEVICES" | wc -l)ALL_DEVICES=""# If clicked, show available devices (both connected and unconnected)if [ "$BLOCK_BUTTON" == 1 ]; thenAVAILABLE_DEVICES=$(get_available_devices)PAIRED_DEVICES=$(get_paired_devices)FILTER=""for word in $AVAILABLE_DEVICES; doif ! [[ " $PAIRED_DEVICES " =~ " $word " ]]; thenFILTER+="$word "fidoneAVAILABLE_DEVICES=$FILTERFILTER=""for word in $PAIRED_DEVICES; doif ! [[ " $CONNECTED_DEVICES " =~ " $word " ]]; thenFILTER+="$word "fidonePAIRED_DEVICES=$FILTERAVAILABLE_DEVICES=$(echo "$AVAILABLE_DEVICES" | xargs)PAIRED_DEVICES=$(echo "$PAIRED_DEVICES" | xargs)CONNECTED_DEVICES=$(echo "$CONNECTED_DEVICES" | xargs)# all connected are paired, all paired are availableif [ -n "$AVAILABLE_DEVICES" ]; thenALL_DEVICES+="<span color=\'#CCCCCC\'>$AVAILABLE_DEVICES</span> "fiif [ -n "$PAIRED_DEVICES" ]; thenALL_DEVICES+="<span color=\'#999999\'>$PAIRED_DEVICES</span> "fiif [ -n "$CONNECTED_DEVICES" ]; thenALL_DEVICES+="<span color=\'#0099cc\'>$CONNECTED_DEVICES</span> "COLOR="#0099cc"fiALL_DEVICES=$(echo "$ALL_DEVICES" | xargs)ECHO="$ALL_DEVICES"# Default display (if there are no connected devices)elseif [ -z "$CONNECTED_DEVICES" ]; thenECHO=""else# Display connected devices countECHO="$CONNECTED_COUNT"COLOR="#0099CC"fifififiif [ -n "$ECHO" ]; thenecho "<span color='$COLOR'>B $ECHO</span>"elseecho "<span color='$COLOR'>B</span>"fiexit 0
#!/bin/bashECHO=""COLOR="#999999"BLUETOOTHCTL=$(which bluetoothctl)# Check if bluetoothctl existsif [ ! -x "$BLUETOOTHCTL" ]; thenECHO="X"# Check if Bluetooth is powered onelseif ! bluetoothctl show | grep -q "Powered: yes"; thenECHO="x"else# Function to get all available devices (both paired and unpaired)get_available_devices() {$BLUETOOTHCTL devices | awk '{$1=$2=""; print $0}' | xargs}# Function to get all paired devicesget_paired_devices() {$BLUETOOTHCTL devices Paired | awk '{$1=$2=""; print $0}' | xargs}# Function to get connected devicesget_connected_devices() {$BLUETOOTHCTL devices Connected | awk '{$1=$2=""; print $0}' | xargs}# List paired devicesCONNECTED_DEVICES=$(get_connected_devices)# Count connected devicesCONNECTED_COUNT=$(echo "$CONNECTED_DEVICES" | wc -l)ALL_DEVICES=""# If clicked, show available devices (both connected and unconnected)if [ "$BLOCK_BUTTON" == 1 ]; thenAVAILABLE_DEVICES=$(get_available_devices)PAIRED_DEVICES=$(get_paired_devices)FILTER=""for word in $AVAILABLE_DEVICES; doif ! [[ " $PAIRED_DEVICES " =~ " $word " ]]; thenFILTER+="$word "fidoneAVAILABLE_DEVICES=$FILTERFILTER=""for word in $PAIRED_DEVICES; doif ! [[ " $CONNECTED_DEVICES " =~ " $word " ]]; thenFILTER+="$word "fidonePAIRED_DEVICES=$FILTERAVAILABLE_DEVICES=$(echo "$AVAILABLE_DEVICES" | xargs)PAIRED_DEVICES=$(echo "$PAIRED_DEVICES" | xargs)CONNECTED_DEVICES=$(echo "$CONNECTED_DEVICES" | xargs)# all connected are paired, all paired are availableif [ -n "$AVAILABLE_DEVICES" ]; thenALL_DEVICES+="<span color=\'#CCCCCC\'>$AVAILABLE_DEVICES</span> "fiif [ -n "$PAIRED_DEVICES" ]; thenALL_DEVICES+="<span color=\'#999999\'>$PAIRED_DEVICES</span> "fiif [ -n "$CONNECTED_DEVICES" ]; thenALL_DEVICES+="<span color=\'#0099cc\'>$CONNECTED_DEVICES</span> "COLOR="#0099cc"fiALL_DEVICES=$(echo "$ALL_DEVICES" | xargs)ECHO="$ALL_DEVICES"# Default display (if there are no connected devices)elseif [ -z "$CONNECTED_DEVICES" ]; thenECHO=""else# Display connected devices countECHO="$CONNECTED_COUNT"COLOR="#0099CC"fifififiif [ -n "$ECHO" ]; thenecho "<span color='$COLOR'>B $ECHO</span>"elseecho "<span color='$COLOR'>B</span>"fiexit 0
#!/usr/bin/env bash# batterybar; displays battery percentage as a bar on i3blocks## Copyright 2015 Keftaa <adnan.37h@gmail.com>## This program 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 2 of the License, or# (at your option) any later version.## This program 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 this program; if not, write to the Free Software# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,# MA 02110-1301, USA.##readarray -t output <<< $(acpi battery)battery_count=${#output[@]}for line in "${output[@]}";dopercentages+=($(echo "$line" | grep -o -m1 '[0-9]\{1,3\}%' | tr -d '%'))statuses+=($(echo "$line" | egrep -o -m1 'Discharging|Charging|AC|Full|Unknown'))remaining=$(echo "$line" | egrep -o -m1 '[0-9][0-9]:[0-9][0-9]')if [[ -n $remaining ]]; thenremainings+=(" ($remaining)")elseremainings+=("")fidonesquares="■"#There are 8 colors that reflect the current battery percentage when#dischargingdis_colors=("${C1:-#FF0000}""${C2:-#FF6666}""${C2:-#FF9999}""${C4:-#FFAAAA}""${C5:-#AAAAAA}""${C6:-#AAAAAA}""${C7:-#AAAAAA}""${C8:-#AAAAAA}")charging_color="${CHARGING_COLOR:-#6699CC}"full_color="${FULL_COLOR:-#CCCCCC}"ac_color="${AC_COLOR:-#535353}"while getopts 1:2:3:4:5:6:7:8:c:f:a:h opt; docase "$opt" in1) dis_colors[0]="$OPTARG";;2) dis_colors[1]="$OPTARG";;3) dis_colors[2]="$OPTARG";;4) dis_colors[3]="$OPTARG";;5) dis_colors[4]="$OPTARG";;6) dis_colors[5]="$OPTARG";;7) dis_colors[6]="$OPTARG";;8) dis_colors[7]="$OPTARG";;c) charging_color="$OPTARG";;f) full_color="$OPTARG";;a) ac_color="$OPTARG";;h) printf "Usage: batterybar [OPTION] colorWhen discharging, there are 8 [1-8] levels colors.You can specify custom colors, for example:batterybar -1 red -2 \"#F6F6F6\" -8 greenYou can also specify the colors for the charging, AC andcharged states:batterybar -c green -f white -a \"#EEEEEE\"\n";exit 0;esacdoneend=$(($battery_count - 1))for i in $(seq 0 $end);doif (( percentages[$i] > 0 && percentages[$i] < 10 )); thensquares="□□□□□"elif (( percentages[$i] >= 10 && percentages[$i] < 20 )); thensquares="■□□□□"elif (( percentages[$i] >= 20 && percentages[$i] < 40 )); thensquares="■■□□□"elif (( percentages[$i] >= 40 && percentages[$i] < 60 )); thensquares="■■■□□"elif (( percentages[$i] >= 60 && percentages[$i] < 80 )); thensquares="■■■■□"elif (( percentages[$i] >= 80 )); thensquares="■■■■■"fiif [[ "${statuses[$i]}" = "Unknown" ]]; thensquares="<sup>?</sup>$squares"ficolor=${ac_color}case "${statuses[$i]}" in"Charging")color="$charging_color";;"Full")color="$full_color";;"AC")color="$ac_color";;"Discharging"|"Unknown")if (( percentages[$i] >= 0 && percentages[$i] < 10 )); thencolor="${dis_colors[0]}"elif (( percentages[$i] >= 10 && percentages[$i] < 20 )); thencolor="${dis_colors[1]}"elif (( percentages[$i] >= 20 && percentages[$i] < 30 )); thencolor="${dis_colors[2]}"elif (( percentages[$i] >= 30 && percentages[$i] < 40 )); thencolor="${dis_colors[3]}"elif (( percentages[$i] >= 40 && percentages[$i] < 60 )); thencolor="${dis_colors[4]}"elif (( percentages[$i] >= 60 && percentages[$i] < 70 )); thencolor="${dis_colors[5]}"elif (( percentages[$i] >= 70 && percentages[$i] < 80 )); thencolor="${dis_colors[6]}"elif (( percentages[$i] >= 80 )); thencolor="${dis_colors[7]}"fi;;esac# Print Battery number if there is more than oneif (( $end > 0 )) ; thenmessage="$message $(($i + 1)):"fiif [[ "$BLOCK_BUTTON" -eq 1 ]]; thenmessage="$message ${statuses[$i]} ${percentages[$i]}%${remainings[i]}"fimessage="$message <span foreground=\"$color\">$squares</span>"doneecho $message
#!/usr/bin/env bash# batterybar; displays battery percentage as a bar on i3blocks## Copyright 2015 Keftaa <adnan.37h@gmail.com>## This program 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 2 of the License, or# (at your option) any later version.## This program 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 this program; if not, write to the Free Software# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,# MA 02110-1301, USA.##readarray -t output <<< $(acpi battery)battery_count=${#output[@]}for line in "${output[@]}";dopercentages+=($(echo "$line" | grep -o -m1 '[0-9]\{1,3\}%' | tr -d '%'))statuses+=($(echo "$line" | egrep -o -m1 'Discharging|Charging|AC|Full|Unknown'))remaining=$(echo "$line" | egrep -o -m1 '[0-9][0-9]:[0-9][0-9]')if [[ -n $remaining ]]; thenremainings+=(" ($remaining)")elseremainings+=("")fidonesquares="■"#There are 8 colors that reflect the current battery percentage when#dischargingdis_colors=("${C1:-#FF0000}""${C2:-#FF6666}""${C2:-#FF9999}""${C4:-#FFAAAA}""${C5:-#AAAAAA}""${C6:-#AAAAAA}""${C7:-#AAAAAA}""${C8:-#AAAAAA}")charging_color="${CHARGING_COLOR:-#6699CC}"full_color="${FULL_COLOR:-#CCCCCC}"ac_color="${AC_COLOR:-#535353}"while getopts 1:2:3:4:5:6:7:8:c:f:a:h opt; docase "$opt" in1) dis_colors[0]="$OPTARG";;2) dis_colors[1]="$OPTARG";;3) dis_colors[2]="$OPTARG";;4) dis_colors[3]="$OPTARG";;5) dis_colors[4]="$OPTARG";;6) dis_colors[5]="$OPTARG";;7) dis_colors[6]="$OPTARG";;8) dis_colors[7]="$OPTARG";;c) charging_color="$OPTARG";;f) full_color="$OPTARG";;a) ac_color="$OPTARG";;h) printf "Usage: batterybar [OPTION] colorWhen discharging, there are 8 [1-8] levels colors.You can specify custom colors, for example:batterybar -1 red -2 \"#F6F6F6\" -8 greenYou can also specify the colors for the charging, AC andcharged states:batterybar -c green -f white -a \"#EEEEEE\"\n";exit 0;esacdoneend=$(($battery_count - 1))for i in $(seq 0 $end);doif (( percentages[$i] > 0 && percentages[$i] < 10 )); thensquares="□□□□□"elif (( percentages[$i] >= 10 && percentages[$i] < 20 )); thensquares="■□□□□"elif (( percentages[$i] >= 20 && percentages[$i] < 40 )); thensquares="■■□□□"elif (( percentages[$i] >= 40 && percentages[$i] < 60 )); thensquares="■■■□□"elif (( percentages[$i] >= 60 && percentages[$i] < 80 )); thensquares="■■■■□"elif (( percentages[$i] >= 80 )); thensquares="■■■■■"fiif [[ "${statuses[$i]}" = "Unknown" ]]; thensquares="<sup>?</sup>$squares"ficolor=${ac_color}case "${statuses[$i]}" in"Charging")color="$charging_color";;"Full")color="$full_color";;"AC")color="$ac_color";;"Discharging"|"Unknown")if (( percentages[$i] >= 0 && percentages[$i] < 10 )); thencolor="${dis_colors[0]}"elif (( percentages[$i] >= 10 && percentages[$i] < 20 )); thencolor="${dis_colors[1]}"elif (( percentages[$i] >= 20 && percentages[$i] < 30 )); thencolor="${dis_colors[2]}"elif (( percentages[$i] >= 30 && percentages[$i] < 40 )); thencolor="${dis_colors[3]}"elif (( percentages[$i] >= 40 && percentages[$i] < 60 )); thencolor="${dis_colors[4]}"elif (( percentages[$i] >= 60 && percentages[$i] < 70 )); thencolor="${dis_colors[5]}"elif (( percentages[$i] >= 70 && percentages[$i] < 80 )); thencolor="${dis_colors[6]}"elif (( percentages[$i] >= 80 )); thencolor="${dis_colors[7]}"fi;;esac# Print Battery number if there is more than oneif (( $end > 0 )) ; thenmessage="$message $(($i + 1)):"fiif [[ "$BLOCK_BUTTON" -eq 1 ]]; thenmessage="$message ${statuses[$i]} ${percentages[$i]}%${remainings[i]}"fimessage="$message <span foreground=\"$color\">$squares</span>"doneecho $message
#!/usr/bin/env python3## Copyright (C) 2016 James Murphy# Licensed under the GPL version 2 only## A battery indicator blocklet script for i3blocksfrom subprocess import check_outputimport osimport reconfig = dict(os.environ)status = check_output(['acpi'], universal_newlines=True)if not status:# stands for no battery foundcolor = config.get("color_10", "red")fulltext = "<span color='{}'><span font='FontAwesome'>\uf00d \uf240</span></span>".format(color)percentleft = 100else:# if there is more than one battery in one laptop, the percentage left is# available for each battery separately, although state and remaining# time for overall block is shown in the status of the first batterybatteries = status.split("\n")state_batteries=[]commasplitstatus_batteries=[]percentleft_batteries=[]time = ""for battery in batteries:if battery!='':state_batteries.append(battery.split(": ")[1].split(", ")[0])commasplitstatus = battery.split(", ")if not time:time = commasplitstatus[-1].strip()# check if it matches a timetime = re.match(r"(\d+):(\d+)", time)if time:time = ":".join(time.groups())timeleft = " ({})".format(time)else:timeleft = ""p = int(commasplitstatus[1].rstrip("%\n"))if p>0:percentleft_batteries.append(p)commasplitstatus_batteries.append(commasplitstatus)state = state_batteries[0]commasplitstatus = commasplitstatus_batteries[0]if percentleft_batteries:percentleft = int(sum(percentleft_batteries)/len(percentleft_batteries))else:percentleft = 0# stands for chargingcolor = config.get("color_charging", "yellow")FA_LIGHTNING = "<span color='{}'><span font='FontAwesome'>\uf0e7</span></span>".format(color)# stands for plugged inFA_PLUG = "<span font='FontAwesome'>\uf1e6</span>"# stands for using batteryFA_BATTERY = "<span font='FontAwesome'>\uf240</span>"# stands for unknown status of batteryFA_QUESTION = "<span font='FontAwesome'>\uf128</span>"if state == "Discharging":fulltext = FA_BATTERY + " "elif state == "Full":fulltext = FA_PLUG + " "timeleft = ""elif state == "Unknown":fulltext = FA_QUESTION + " " + FA_BATTERY + " "timeleft = ""else:fulltext = FA_LIGHTNING + " " + FA_PLUG + " "def color(percent):if percent < 10:# exit code 33 will turn background redreturn config.get("color_10", "#FFFFFF")if percent < 20:return config.get("color_20", "#FF3300")if percent < 30:return config.get("color_30", "#FF6600")if percent < 40:return config.get("color_40", "#FF9900")if percent < 50:return config.get("color_50", "#FFCC00")if percent < 60:return config.get("color_60", "#FFFF00")if percent < 70:return config.get("color_70", "#FFFF33")if percent < 80:return config.get("color_80", "#FFFF66")return config.get("color_full", "#FFFFFF")form = '<span color="{}">{}%</span>'fulltext += form.format(color(percentleft), percentleft)fulltext += timeleftprint(fulltext)print(fulltext)if percentleft < 10:exit(33)
#!/usr/bin/env python3## Copyright (C) 2016 James Murphy# Licensed under the GPL version 2 only## A battery indicator blocklet script for i3blocksfrom subprocess import check_outputimport osimport reconfig = dict(os.environ)status = check_output(['acpi'], universal_newlines=True)if not status:# stands for no battery foundcolor = config.get("color_10", "red")fulltext = "<span color='{}'><span font='FontAwesome'>\uf00d \uf240</span></span>".format(color)percentleft = 100else:# if there is more than one battery in one laptop, the percentage left is# available for each battery separately, although state and remaining# time for overall block is shown in the status of the first batterybatteries = status.split("\n")state_batteries=[]commasplitstatus_batteries=[]percentleft_batteries=[]time = ""for battery in batteries:if battery!='':state_batteries.append(battery.split(": ")[1].split(", ")[0])commasplitstatus = battery.split(", ")if not time:time = commasplitstatus[-1].strip()# check if it matches a timetime = re.match(r"(\d+):(\d+)", time)if time:time = ":".join(time.groups())timeleft = " ({})".format(time)else:timeleft = ""p = int(commasplitstatus[1].rstrip("%\n"))if p>0:percentleft_batteries.append(p)commasplitstatus_batteries.append(commasplitstatus)state = state_batteries[0]commasplitstatus = commasplitstatus_batteries[0]if percentleft_batteries:percentleft = int(sum(percentleft_batteries)/len(percentleft_batteries))else:percentleft = 0# stands for chargingcolor = config.get("color_charging", "yellow")FA_LIGHTNING = "<span color='{}'><span font='FontAwesome'>\uf0e7</span></span>".format(color)# stands for plugged inFA_PLUG = "<span font='FontAwesome'>\uf1e6</span>"# stands for using batteryFA_BATTERY = "<span font='FontAwesome'>\uf240</span>"# stands for unknown status of batteryFA_QUESTION = "<span font='FontAwesome'>\uf128</span>"if state == "Discharging":fulltext = FA_BATTERY + " "elif state == "Full":fulltext = FA_PLUG + " "timeleft = ""elif state == "Unknown":fulltext = FA_QUESTION + " " + FA_BATTERY + " "timeleft = ""else:fulltext = FA_LIGHTNING + " " + FA_PLUG + " "def color(percent):if percent < 10:# exit code 33 will turn background redreturn config.get("color_10", "#FFFFFF")if percent < 20:return config.get("color_20", "#FF3300")if percent < 30:return config.get("color_30", "#FF6600")if percent < 40:return config.get("color_40", "#FF9900")if percent < 50:return config.get("color_50", "#FFCC00")if percent < 60:return config.get("color_60", "#FFFF00")if percent < 70:return config.get("color_70", "#FFFF33")if percent < 80:return config.get("color_80", "#FFFF66")return config.get("color_full", "#FFFFFF")form = '<span color="{}">{}%</span>'fulltext += form.format(color(percentleft), percentleft)fulltext += timeleftprint(fulltext)print(fulltext)if percentleft < 10:exit(33)
#!/usr/bin/env python3"""poly-battery-status-py: Generates a pretty status-bar string for multi-battery systems on Linux.Copyright (C) 2020 Falke CarlsenThis program is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program. If not, see <https://www.gnu.org/licenses/>."""import reimport sysfrom enum import Enumfrom pathlib import PathPSEUDO_FS_PATH = "/sys/class/power_supply/"CURRENT_CHARGE_FILENAME = "energy_now"MAX_CHARGE_FILENAME = "energy_full"POWER_DRAW_FILENAME = "power_now"TLP_THRESHOLD_PERCENTAGE = 1.0PERCENTAGE_FORMAT = ".2%"if len(sys.argv) > 1:# parsing thresholdtry:TLP_THRESHOLD_PERCENTAGE = float(sys.argv[1])except ValueError:print(f"[ERROR]: Could not convert '{sys.argv[1]}' into a float.")if len(sys.argv) > 2:# parsing formattingPERCENTAGE_FORMAT = sys.argv[2]class Status(Enum):CHARGING = 1DISCHARGING = 2PASSIVE = 3class Configuration:time_to_completion: intpercentage: floatstatus: Statusdef __init__(self, time_to_completion, percentage, status):self.time_to_completion = time_to_completionself.percentage = percentageself.status = statusclass Battery:status: Statuscurrent_charge: intmax_charge: intpower_draw: intdef __init__(self, status, current_charge, max_charge, power_draw):self.Status = statusself.current_charge = current_chargeself.max_charge = max_chargeself.power_draw = power_drawdef get_configuration() -> Configuration:# get all batteries on systembatteries = []for x in Path(PSEUDO_FS_PATH).iterdir():bat_name = str(x.parts[len(x.parts) - 1])if re.match("^BAT\d+$", bat_name):batteries.append(Battery(get_status(bat_name),get_current_charge(bat_name),get_max_charge(bat_name),get_power_draw(bat_name)))# calculate global status, assumes that if a battery is not passive, it will be discharging or chargingconfig_status = Status.PASSIVEfor bat in batteries:if bat.Status == Status.CHARGING:config_status = Status.CHARGINGbreakelif bat.Status == Status.DISCHARGING:config_status = Status.DISCHARGINGbreak# construct and return configurationreturn Configuration(calc_time(batteries, config_status), calc_percentage(batteries), config_status)def get_status(bat_name: str) -> Status:raw_status = Path(f"{PSEUDO_FS_PATH}{bat_name}/status").open().read().strip()if raw_status == "Unknown" or raw_status == "Full":return Status.PASSIVEelif raw_status == "Charging":return Status.CHARGINGelif raw_status == "Discharging":return Status.DISCHARGINGelse:raise ValueErrordef get_current_charge(bat_name: str) -> int:return int(Path(f"{PSEUDO_FS_PATH}{bat_name}/{CURRENT_CHARGE_FILENAME}").open().read().strip())def get_max_charge(bat_name: str) -> int:return int(Path(f"{PSEUDO_FS_PATH}{bat_name}/{MAX_CHARGE_FILENAME}").open().read().strip())def get_power_draw(bat_name: str) -> int:return int(Path(f"{PSEUDO_FS_PATH}{bat_name}/{POWER_DRAW_FILENAME}").open().read().strip())def calc_time(batteries: list, status: Status) -> int:if status == Status.PASSIVE:return 0# get total metrics on configurationtotal_current_charge = sum([bat.current_charge for bat in batteries])total_max_charge = sum([bat.max_charge for bat in batteries])total_power_draw = sum([bat.power_draw for bat in batteries])if total_power_draw == 0:return 0if status == Status.DISCHARGING:# return number of seconds until emptyreturn (total_current_charge / total_power_draw) * 3600elif status == Status.CHARGING:# return number of seconds until (optionally relatively) chargedreturn (((total_max_charge * TLP_THRESHOLD_PERCENTAGE) - total_current_charge) / total_power_draw) * 3600def calc_percentage(batteries: list) -> float:total_max_charge = sum([bat.max_charge for bat in batteries])total_current_charge = sum([bat.current_charge for bat in batteries])return total_current_charge / total_max_chargedef calc_display_time(status: Status, seconds: int) -> str:hours = int(seconds // 3600)minutes = int((seconds % 3600) / 60)if status == Status.PASSIVE:return ""# assume charging initially if not passivedirection = "+"if status == Status.DISCHARGING:direction = "-"# format output digitally, e.g. (+0:09)return f" ({direction}{hours}:{minutes:02})"def print_status(config: Configuration):print(f"{config.percentage:{PERCENTAGE_FORMAT}}{calc_display_time(config.status, config.time_to_completion)}")def main():print_status(get_configuration())if __name__ == '__main__':main()
#!/usr/bin/env python3"""poly-battery-status-py: Generates a pretty status-bar string for multi-battery systems on Linux.Copyright (C) 2020 Falke CarlsenThis program is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program. If not, see <https://www.gnu.org/licenses/>."""import reimport sysfrom enum import Enumfrom pathlib import PathPSEUDO_FS_PATH = "/sys/class/power_supply/"CURRENT_CHARGE_FILENAME = "energy_now"MAX_CHARGE_FILENAME = "energy_full"POWER_DRAW_FILENAME = "power_now"TLP_THRESHOLD_PERCENTAGE = 1.0PERCENTAGE_FORMAT = ".2%"if len(sys.argv) > 1:# parsing thresholdtry:TLP_THRESHOLD_PERCENTAGE = float(sys.argv[1])except ValueError:print(f"[ERROR]: Could not convert '{sys.argv[1]}' into a float.")if len(sys.argv) > 2:# parsing formattingPERCENTAGE_FORMAT = sys.argv[2]class Status(Enum):CHARGING = 1DISCHARGING = 2PASSIVE = 3class Configuration:time_to_completion: intpercentage: floatstatus: Statusdef __init__(self, time_to_completion, percentage, status):self.time_to_completion = time_to_completionself.percentage = percentageself.status = statusclass Battery:status: Statuscurrent_charge: intmax_charge: intpower_draw: intdef __init__(self, status, current_charge, max_charge, power_draw):self.Status = statusself.current_charge = current_chargeself.max_charge = max_chargeself.power_draw = power_drawdef get_configuration() -> Configuration:# get all batteries on systembatteries = []for x in Path(PSEUDO_FS_PATH).iterdir():bat_name = str(x.parts[len(x.parts) - 1])if re.match("^BAT\d+$", bat_name):batteries.append(Battery(get_status(bat_name),get_current_charge(bat_name),get_max_charge(bat_name),get_power_draw(bat_name)))# calculate global status, assumes that if a battery is not passive, it will be discharging or chargingconfig_status = Status.PASSIVEfor bat in batteries:if bat.Status == Status.CHARGING:config_status = Status.CHARGINGbreakelif bat.Status == Status.DISCHARGING:config_status = Status.DISCHARGINGbreak# construct and return configurationreturn Configuration(calc_time(batteries, config_status), calc_percentage(batteries), config_status)def get_status(bat_name: str) -> Status:raw_status = Path(f"{PSEUDO_FS_PATH}{bat_name}/status").open().read().strip()if raw_status == "Unknown" or raw_status == "Full":return Status.PASSIVEelif raw_status == "Charging":return Status.CHARGINGelif raw_status == "Discharging":return Status.DISCHARGINGelse:raise ValueErrordef get_current_charge(bat_name: str) -> int:return int(Path(f"{PSEUDO_FS_PATH}{bat_name}/{CURRENT_CHARGE_FILENAME}").open().read().strip())def get_max_charge(bat_name: str) -> int:return int(Path(f"{PSEUDO_FS_PATH}{bat_name}/{MAX_CHARGE_FILENAME}").open().read().strip())def get_power_draw(bat_name: str) -> int:return int(Path(f"{PSEUDO_FS_PATH}{bat_name}/{POWER_DRAW_FILENAME}").open().read().strip())def calc_time(batteries: list, status: Status) -> int:if status == Status.PASSIVE:return 0# get total metrics on configurationtotal_current_charge = sum([bat.current_charge for bat in batteries])total_max_charge = sum([bat.max_charge for bat in batteries])total_power_draw = sum([bat.power_draw for bat in batteries])if total_power_draw == 0:return 0if status == Status.DISCHARGING:# return number of seconds until emptyreturn (total_current_charge / total_power_draw) * 3600elif status == Status.CHARGING:# return number of seconds until (optionally relatively) chargedreturn (((total_max_charge * TLP_THRESHOLD_PERCENTAGE) - total_current_charge) / total_power_draw) * 3600def calc_percentage(batteries: list) -> float:total_max_charge = sum([bat.max_charge for bat in batteries])total_current_charge = sum([bat.current_charge for bat in batteries])return total_current_charge / total_max_chargedef calc_display_time(status: Status, seconds: int) -> str:hours = int(seconds // 3600)minutes = int((seconds % 3600) / 60)if status == Status.PASSIVE:return ""# assume charging initially if not passivedirection = "+"if status == Status.DISCHARGING:direction = "-"# format output digitally, e.g. (+0:09)return f" ({direction}{hours}:{minutes:02})"def print_status(config: Configuration):print(f"{config.percentage:{PERCENTAGE_FORMAT}}{calc_display_time(config.status, config.time_to_completion)}")def main():print_status(get_configuration())if __name__ == '__main__':main()
#!/usr/bin/env perl## Copyright 2014 Pierre Mavro <deimos@deimos.fr># Copyright 2014 Vivien Didelot <vivien@didelot.org>## Licensed under the terms of the GNU GPL v3, or any later version.## This script is meant to use with i3blocks. It parses the output of the "acpi"# command (often provided by a package of the same name) to read the status of# the battery, and eventually its remaining time (to full charge or discharge).## The color will gradually change for a percentage below 85%, and the urgency# (exit code 33) is set if there is less that 5% remaining.use strict;use warnings;use utf8;my $acpi;my $status;my $percent;my $ac_adapt;my $full_text;my $short_text;my $bat_number = $ENV{BAT_NUMBER} || 0;my $label = $ENV{LABEL} || "";# read the first line of the "acpi" command outputopen (ACPI, "acpi -b 2>/dev/null| grep 'Battery $bat_number' |") or die;$acpi = <ACPI>;close(ACPI);# fail on unexpected outputif (not defined($acpi)) {# don't print anything to stderr if there is no batteryexit(0);}elsif ($acpi !~ /: ([\w\s]+), (\d+)%/) {die "$acpi\n";}$status = $1;$percent = $2;$full_text = "$label$percent%";if ($status eq 'Discharging') {$full_text .= ' DIS';} elsif ($status eq 'Charging') {$full_text .= ' CHR';} elsif ($status eq 'Unknown') {open (AC_ADAPTER, "acpi -a |") or die;$ac_adapt = <AC_ADAPTER>;close(AC_ADAPTER);if ($ac_adapt =~ /: ([\w-]+)/) {$ac_adapt = $1;if ($ac_adapt eq 'on-line') {$full_text .= ' CHR';} elsif ($ac_adapt eq 'off-line') {$full_text .= ' DIS';}}}$short_text = $full_text;if ($acpi =~ /(\d\d:\d\d):/) {$full_text .= " ($1)";}# print textprint "$full_text\n";print "$short_text\n";# consider color and urgent flag only on dischargeif ($status eq 'Discharging') {if ($percent < 20) {print "#FF0000\n";} elsif ($percent < 40) {print "#FFAE00\n";} elsif ($percent < 60) {print "#FFF600\n";} elsif ($percent < 85) {print "#A8FF00\n";}if ($percent < 5) {exit(33);}}exit(0);
#!/usr/bin/env perl## Copyright 2014 Pierre Mavro <deimos@deimos.fr># Copyright 2014 Vivien Didelot <vivien@didelot.org>## Licensed under the terms of the GNU GPL v3, or any later version.## This script is meant to use with i3blocks. It parses the output of the "acpi"# command (often provided by a package of the same name) to read the status of# the battery, and eventually its remaining time (to full charge or discharge).## The color will gradually change for a percentage below 85%, and the urgency# (exit code 33) is set if there is less that 5% remaining.use strict;use warnings;use utf8;my $acpi;my $status;my $percent;my $ac_adapt;my $full_text;my $short_text;my $bat_number = $ENV{BAT_NUMBER} || 0;my $label = $ENV{LABEL} || "";# read the first line of the "acpi" command outputopen (ACPI, "acpi -b 2>/dev/null| grep 'Battery $bat_number' |") or die;$acpi = <ACPI>;close(ACPI);# fail on unexpected outputif (not defined($acpi)) {# don't print anything to stderr if there is no batteryexit(0);}elsif ($acpi !~ /: ([\w\s]+), (\d+)%/) {die "$acpi\n";}$status = $1;$percent = $2;$full_text = "$label$percent%";if ($status eq 'Discharging') {$full_text .= ' DIS';} elsif ($status eq 'Charging') {$full_text .= ' CHR';} elsif ($status eq 'Unknown') {open (AC_ADAPTER, "acpi -a |") or die;$ac_adapt = <AC_ADAPTER>;close(AC_ADAPTER);if ($ac_adapt =~ /: ([\w-]+)/) {$ac_adapt = $1;if ($ac_adapt eq 'on-line') {$full_text .= ' CHR';} elsif ($ac_adapt eq 'off-line') {$full_text .= ' DIS';}}}$short_text = $full_text;if ($acpi =~ /(\d\d:\d\d):/) {$full_text .= " ($1)";}# print textprint "$full_text\n";print "$short_text\n";# consider color and urgent flag only on dischargeif ($status eq 'Discharging') {if ($percent < 20) {print "#FF0000\n";} elsif ($percent < 40) {print "#FFAE00\n";} elsif ($percent < 60) {print "#FFF600\n";} elsif ($percent < 85) {print "#A8FF00\n";}if ($percent < 5) {exit(33);}}exit(0);
#!/usr/bin/env bash## Copyright (C) 2015 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to monitor bandwidth usageiface="${BLOCK_INSTANCE}"iface="${IFACE:-$iface}"dt="${DT:-3}"unit="${UNIT:-Mb}"LABEL="${LABEL:-<span font='FontAwesome'> </span>}" # down arrow up arrowprintf_command="${PRINTF_COMMAND:-"printf \"${LABEL}%-5.1f/%5.1f %s/s\\n\", rx, wx, unit;"}"function default_interface {ip route | awk '/^default via/ {print $5; exit}'}function check_proc_net_dev {if [ ! -f "/proc/net/dev" ]; thenecho "/proc/net/dev not found"exit 1fi}function list_interfaces {check_proc_net_devecho "Interfaces in /proc/net/dev:"grep -o "^[^:]\\+:" /proc/net/dev | tr -d " :"}while getopts i:t:u:p:lh opt; docase "$opt" ini) iface="$OPTARG" ;;t) dt="$OPTARG" ;;u) unit="$OPTARG" ;;p) printf_command="$OPTARG" ;;l) list_interfaces && exit 0 ;;h) printf \"Usage: bandwidth3 [-i interface] [-t time] [-u unit] [-p printf_command] [-l] [-h]Options:-i\tNetwork interface to measure. Default determined using \`ip route\`.-t\tTime interval in seconds between measurements. Default: 3-u\tUnits to measure bytes in. Default: Mb\tAllowed units: Kb, KB, Mb, MB, Gb, GB, Tb, TB\tUnits may have optional it/its/yte/ytes on the end, e.g. Mbits, KByte-p\tAwk command to be called after a measurement is made.\tDefault: printf \"<span font='FontAwesome'> </span>%%-5.1f/%%5.1f %%s/s\\\\n\", rx, wx, unit;\tExposed variables: rx, wx, tx, unit, iface-l\tList available interfaces in /proc/net/dev-h\tShow this help text" && exit 0;;esacdonecheck_proc_net_deviface="${iface:-$(default_interface)}"while [ -z "$iface" ]; doecho No default interfacesleep "$dt"iface=$(default_interface)donecase "$unit" inKb|Kbit|Kbits) bytes_per_unit=$((1024 / 8));;KB|KByte|KBytes) bytes_per_unit=$((1024));;Mb|Mbit|Mbits) bytes_per_unit=$((1024 * 1024 / 8));;MB|MByte|MBytes) bytes_per_unit=$((1024 * 1024));;Gb|Gbit|Gbits) bytes_per_unit=$((1024 * 1024 * 1024 / 8));;GB|GByte|GBytes) bytes_per_unit=$((1024 * 1024 * 1024));;Tb|Tbit|Tbits) bytes_per_unit=$((1024 * 1024 * 1024 * 1024 / 8));;TB|TByte|TBytes) bytes_per_unit=$((1024 * 1024 * 1024 * 1024));;*) echo Bad unit "$unit" && exit 1;;esacscalar=$((bytes_per_unit * dt))init_line=$(cat /proc/net/dev | grep "^[ ]*$iface:")if [ -z "$init_line" ]; thenecho Interface not found in /proc/net/dev: "$iface"exit 1fiinit_received=$(awk '{print $2}' <<< $init_line)init_sent=$(awk '{print $10}' <<< $init_line)(while true; do cat /proc/net/dev; sleep "$dt"; done) |\stdbuf -oL grep "^[ ]*$iface:" |\awk -v scalar="$scalar" -v unit="$unit" -v iface="$iface" 'BEGIN{old_received='"$init_received"';old_sent='"$init_sent"'}{received=$2sent=$10rx=(received-old_received)/scalar;wx=(sent-old_sent)/scalar;tx=rx+wr;old_received=received;old_sent=sent;if(rx >= 0 && wx >= 0){'"$printf_command"';fflush(stdout);}}'
#!/usr/bin/env bash## Copyright (C) 2015 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to monitor bandwidth usageiface="${BLOCK_INSTANCE}"iface="${IFACE:-$iface}"dt="${DT:-3}"unit="${UNIT:-Mb}"LABEL="${LABEL:-<span font='FontAwesome'> </span>}" # down arrow up arrowprintf_command="${PRINTF_COMMAND:-"printf \"${LABEL}%-5.1f/%5.1f %s/s\\n\", rx, wx, unit;"}"function default_interface {ip route | awk '/^default via/ {print $5; exit}'}function check_proc_net_dev {if [ ! -f "/proc/net/dev" ]; thenecho "/proc/net/dev not found"exit 1fi}function list_interfaces {check_proc_net_devecho "Interfaces in /proc/net/dev:"grep -o "^[^:]\\+:" /proc/net/dev | tr -d " :"}while getopts i:t:u:p:lh opt; docase "$opt" ini) iface="$OPTARG" ;;t) dt="$OPTARG" ;;u) unit="$OPTARG" ;;p) printf_command="$OPTARG" ;;l) list_interfaces && exit 0 ;;h) printf \"Usage: bandwidth3 [-i interface] [-t time] [-u unit] [-p printf_command] [-l] [-h]Options:-i\tNetwork interface to measure. Default determined using \`ip route\`.-t\tTime interval in seconds between measurements. Default: 3-u\tUnits to measure bytes in. Default: Mb\tAllowed units: Kb, KB, Mb, MB, Gb, GB, Tb, TB\tUnits may have optional it/its/yte/ytes on the end, e.g. Mbits, KByte-p\tAwk command to be called after a measurement is made.\tDefault: printf \"<span font='FontAwesome'> </span>%%-5.1f/%%5.1f %%s/s\\\\n\", rx, wx, unit;\tExposed variables: rx, wx, tx, unit, iface-l\tList available interfaces in /proc/net/dev-h\tShow this help text" && exit 0;;esacdonecheck_proc_net_deviface="${iface:-$(default_interface)}"while [ -z "$iface" ]; doecho No default interfacesleep "$dt"iface=$(default_interface)donecase "$unit" inKb|Kbit|Kbits) bytes_per_unit=$((1024 / 8));;KB|KByte|KBytes) bytes_per_unit=$((1024));;Mb|Mbit|Mbits) bytes_per_unit=$((1024 * 1024 / 8));;MB|MByte|MBytes) bytes_per_unit=$((1024 * 1024));;Gb|Gbit|Gbits) bytes_per_unit=$((1024 * 1024 * 1024 / 8));;GB|GByte|GBytes) bytes_per_unit=$((1024 * 1024 * 1024));;Tb|Tbit|Tbits) bytes_per_unit=$((1024 * 1024 * 1024 * 1024 / 8));;TB|TByte|TBytes) bytes_per_unit=$((1024 * 1024 * 1024 * 1024));;*) echo Bad unit "$unit" && exit 1;;esacscalar=$((bytes_per_unit * dt))init_line=$(cat /proc/net/dev | grep "^[ ]*$iface:")if [ -z "$init_line" ]; thenecho Interface not found in /proc/net/dev: "$iface"exit 1fiinit_received=$(awk '{print $2}' <<< $init_line)init_sent=$(awk '{print $10}' <<< $init_line)(while true; do cat /proc/net/dev; sleep "$dt"; done) |\stdbuf -oL grep "^[ ]*$iface:" |\awk -v scalar="$scalar" -v unit="$unit" -v iface="$iface" 'BEGIN{old_received='"$init_received"';old_sent='"$init_sent"'}{received=$2sent=$10rx=(received-old_received)/scalar;wx=(sent-old_sent)/scalar;tx=rx+wr;old_received=received;old_sent=sent;if(rx >= 0 && wx >= 0){'"$printf_command"';fflush(stdout);}}'
#!/usr/bin/env bash# Copyright (C) 2012 Stefan Breunig <stefan+measure-net-speed@mathphys.fsk.uni-heidelberg.de># Copyright (C) 2014 kaueraal# Copyright (C) 2015 Thiago Perrotta <perrotta dot thiago at poli dot ufrj dot br># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# Get custom IN and OUT labels if provided by command line argumentswhile [[ $# -gt 1 ]]; dokey="$1"case "$key" in-i|--inlabel)INLABEL="$2"shift;;-o|--outlabel)OUTLABEL="$2"shift;;esacshiftdone[[ -z "$INLABEL" ]] && INLABEL="IN "[[ -z "$OUTLABEL" ]] && OUTLABEL="OUT "# Use the provided interface, otherwise the device used for the default route.if [[ -z $INTERFACE ]] && [[ -n $BLOCK_INSTANCE ]]; thenINTERFACE=$BLOCK_INSTANCEelif [[ -z $INTERFACE ]]; thenINTERFACE=$(ip route | awk '/^default/ { print $5 ; exit }')fi# Exit if there is no default route[[ -z "$INTERFACE" ]] && exit# Issue #36 compliant.if ! [ -e "/sys/class/net/${INTERFACE}/operstate" ] || \(! [ "$TREAT_UNKNOWN_AS_UP" = "1" ] &&! [ "`cat /sys/class/net/${INTERFACE}/operstate`" = "up" ])thenecho "$INTERFACE down"echo "$INTERFACE down"echo "#FF0000"exit 0fi# path to store the old results inpath="/tmp/$(basename $0)-${INTERFACE}"# grabbing data for each adapter.read rx < "/sys/class/net/${INTERFACE}/statistics/rx_bytes"read tx < "/sys/class/net/${INTERFACE}/statistics/tx_bytes"# get timetime="$(date +%s)"# write current data if file does not exist. Do not exit, this will cause# problems if this file is sourced instead of executed as another process.if ! [[ -f "${path}" ]]; thenecho "${time} ${rx} ${tx}" > "${path}"chmod 0666 "${path}"fi# read previous state and update data storageread old < "${path}"echo "${time} ${rx} ${tx}" > "${path}"# parse old data and calc time passedold=(${old//;/ })time_diff=$(( $time - ${old[0]} ))# sanity check: has a positive amount of time passed[[ "${time_diff}" -gt 0 ]] || exit# calc bytes transferred, and their rate in byte/srx_diff=$(( $rx - ${old[1]} ))tx_diff=$(( $tx - ${old[2]} ))rx_rate=$(( $rx_diff / $time_diff ))tx_rate=$(( $tx_diff / $time_diff ))# shift by 10 bytes to get KiB/s. If the value is larger than# 1024^2 = 1048576, then display MiB/s instead# incomingecho -n "$INLABEL"rx_kib=$(( $rx_rate >> 10 ))if hash bc 2>/dev/null && [[ "$rx_rate" -gt 1048576 ]]; thenprintf '%sM' "`echo "scale=1; $rx_kib / 1024" | bc`"elseecho -n "${rx_kib}K"fiecho -n " "# outgoingecho -n "$OUTLABEL"tx_kib=$(( $tx_rate >> 10 ))if hash bc 2>/dev/null && [[ "$tx_rate" -gt 1048576 ]]; thenprintf '%sM\n' "`echo "scale=1; $tx_kib / 1024" | bc`"elseecho "${tx_kib}K"fi
#!/usr/bin/env bash# Copyright (C) 2012 Stefan Breunig <stefan+measure-net-speed@mathphys.fsk.uni-heidelberg.de># Copyright (C) 2014 kaueraal# Copyright (C) 2015 Thiago Perrotta <perrotta dot thiago at poli dot ufrj dot br># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.# Get custom IN and OUT labels if provided by command line argumentswhile [[ $# -gt 1 ]]; dokey="$1"case "$key" in-i|--inlabel)INLABEL="$2"shift;;-o|--outlabel)OUTLABEL="$2"shift;;esacshiftdone[[ -z "$INLABEL" ]] && INLABEL="IN "[[ -z "$OUTLABEL" ]] && OUTLABEL="OUT "# Use the provided interface, otherwise the device used for the default route.if [[ -z $INTERFACE ]] && [[ -n $BLOCK_INSTANCE ]]; thenINTERFACE=$BLOCK_INSTANCEelif [[ -z $INTERFACE ]]; thenINTERFACE=$(ip route | awk '/^default/ { print $5 ; exit }')fi# Exit if there is no default route[[ -z "$INTERFACE" ]] && exit# Issue #36 compliant.if ! [ -e "/sys/class/net/${INTERFACE}/operstate" ] || \(! [ "$TREAT_UNKNOWN_AS_UP" = "1" ] &&! [ "`cat /sys/class/net/${INTERFACE}/operstate`" = "up" ])thenecho "$INTERFACE down"echo "$INTERFACE down"echo "#FF0000"exit 0fi# path to store the old results inpath="/tmp/$(basename $0)-${INTERFACE}"# grabbing data for each adapter.read rx < "/sys/class/net/${INTERFACE}/statistics/rx_bytes"read tx < "/sys/class/net/${INTERFACE}/statistics/tx_bytes"# get timetime="$(date +%s)"# write current data if file does not exist. Do not exit, this will cause# problems if this file is sourced instead of executed as another process.if ! [[ -f "${path}" ]]; thenecho "${time} ${rx} ${tx}" > "${path}"chmod 0666 "${path}"fi# read previous state and update data storageread old < "${path}"echo "${time} ${rx} ${tx}" > "${path}"# parse old data and calc time passedold=(${old//;/ })time_diff=$(( $time - ${old[0]} ))# sanity check: has a positive amount of time passed[[ "${time_diff}" -gt 0 ]] || exit# calc bytes transferred, and their rate in byte/srx_diff=$(( $rx - ${old[1]} ))tx_diff=$(( $tx - ${old[2]} ))rx_rate=$(( $rx_diff / $time_diff ))tx_rate=$(( $tx_diff / $time_diff ))# shift by 10 bytes to get KiB/s. If the value is larger than# 1024^2 = 1048576, then display MiB/s instead# incomingecho -n "$INLABEL"rx_kib=$(( $rx_rate >> 10 ))if hash bc 2>/dev/null && [[ "$rx_rate" -gt 1048576 ]]; thenprintf '%sM' "`echo "scale=1; $rx_kib / 1024" | bc`"elseecho -n "${rx_kib}K"fiecho -n " "# outgoingecho -n "$OUTLABEL"tx_kib=$(( $tx_rate >> 10 ))if hash bc 2>/dev/null && [[ "$tx_rate" -gt 1048576 ]]; thenprintf '%sM\n' "`echo "scale=1; $tx_kib / 1024" | bc`"elseecho "${tx_kib}K"fi
#!/usr/bin/env bash# Show the screen brightness value given by `xbacklight`.# Clicking uses `xset` to turn off the backlight, scrolling increases or decreases# the brightness.# Copyright 2019 Johannes Lange## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.STEP_SIZE=${STEP_SIZE:-5}USE_SUDO=${USE_SUDO:-0}# whether to use `sudo` for changing the brightness (requires a NOPASSWD rule)if [[ "$USE_SUDO" == "0" ]] ; thenXBACKLIGHT_SET="xbacklight"elseXBACKLIGHT_SET="sudo xbacklight"ficase $BLOCK_BUTTON in3) xset dpms force off ;; # right click4) $XBACKLIGHT_SET -inc "$STEP_SIZE" ;; # scroll up5) $XBACKLIGHT_SET -dec "$STEP_SIZE" ;; # scroll down, decreaseesacBRIGHTNESS=$(xbacklight -get | cut -f1 -d'.')echo "${BRIGHTNESS}%"
#!/usr/bin/env bash# Show the screen brightness value given by `xbacklight`.# Clicking uses `xset` to turn off the backlight, scrolling increases or decreases# the brightness.# Copyright 2019 Johannes Lange## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.STEP_SIZE=${STEP_SIZE:-5}USE_SUDO=${USE_SUDO:-0}# whether to use `sudo` for changing the brightness (requires a NOPASSWD rule)if [[ "$USE_SUDO" == "0" ]] ; thenXBACKLIGHT_SET="xbacklight"elseXBACKLIGHT_SET="sudo xbacklight"ficase $BLOCK_BUTTON in3) xset dpms force off ;; # right click4) $XBACKLIGHT_SET -inc "$STEP_SIZE" ;; # scroll up5) $XBACKLIGHT_SET -dec "$STEP_SIZE" ;; # scroll down, decreaseesacBRIGHTNESS=$(xbacklight -get | cut -f1 -d'.')echo "${BRIGHTNESS}%"
#!/usr/bin/env python3# List available updates from the Arch User Repository (AUR)# Copyright 2018 Johannes Lange## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import jsonimport osimport requestsimport socketimport subprocess as spblock_button = os.environ['BLOCK_BUTTON'] if 'BLOCK_BUTTON' in os.environ else Noneblock_button = int(block_button) if block_button else Noneclass Args(object):def add_argument(self, name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]if arg_type == list:val = val.split()val = arg_type(val)setattr(self, name.lower(), val)return valargs = Args()args.add_argument('UPDATE_COLOR', 'yellow')args.add_argument('QUIET', 0, int)args.add_argument('IGNORE', [], list)args.add_argument('CACHE_UPDATES', 0, int)args.add_argument('FORCE_IPV4', 1, int)def version_in_aur(pkg):p = {'v': '5', 'type': 'search', 'by': 'name', 'arg': pkg}response = requests.get('https://aur.archlinux.org/rpc/', params=p)response = response.json()for r in response['results']:if r['Name'] == pkg:return r['Version']return "NotFound"def vcs_version(pkg, ver):""" Try to find a sensible version for VSC packagesIf pkg looks like a VCS package according tohttps://wiki.archlinux.org/index.php/VCS_package_guidelinestry to extract a sensible (= comparable) version number."""suffices = ['-cvs', '-svn', '-hg', '-darcs', '-bzr', '-git']if not any(pkg.endswith(suffix) for suffix in suffices):# does not look like a VCS packagereturn verif '.r' in ver:# of the form RELEASE.rREVISION: only use the releasereturn ver.split('.r')[0]# no base release to compare, just return Nonereturn Noneif args.force_ipv4:# This is useful, because the AUR API often gets timeouts with# IPV6 and the call does not return.# monkey-patch this function to always return the IPV4-version,# even if capable of IPV6requests.packages.urllib3.util.connection.allowed_gai_family = (lambda: socket.AF_INET)# show the list of updates already cachedif args.cache_updates and block_button in [2, 3]:if '_update_cache' in os.environ:updates = os.environ['_update_cache']else:updates = 'no updates cached'sp.call(['notify-send', 'AUR updates', updates or 'up to date'])# get list of foreign packages -- assumed to be from the AURpackages = sp.check_output(['pacman', '-Qm']).decode('utf8')installed_version = {}for pkg in packages.split('\n'):if not pkg:continuepkg, ver = pkg.split()installed_version[pkg] = verupdates = []for pkg in installed_version.keys():if pkg in args.ignore:continuev_aur = version_in_aur(pkg)v_inst = installed_version[pkg]if vcs_version(pkg, v_aur) != vcs_version(pkg, v_inst):updates.append(pkg + ' (%s -> %s)' % (v_inst, v_aur))# create the message for the blockn_updates = len(updates)msg = ''if n_updates > 0:msg = "<span color='{0}'>{1} AUR updates</span>".format(args.update_color, n_updates)elif not args.quiet:msg = 'AUR up to date'# turn it into a json messagemsg = {'full_text': msg}# cache the new updates listif args.cache_updates:msg['_update_cache'] = '\n'.join(updates)print(json.dumps(msg))# if you don't use caching, show the new list of updatesif not args.cache_updates and block_button in [2, 3]:sp.call(['notify-send', 'AUR updates', '\n'.join(updates) or 'up to date'])if not 'BLOCK_NAME' in os.environ and n_updates > 0:# not called by i3blocks: show the complete listprint('\n'.join(updates))
#!/usr/bin/env python3# List available updates from the Arch User Repository (AUR)# Copyright 2018 Johannes Lange## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import jsonimport osimport requestsimport socketimport subprocess as spblock_button = os.environ['BLOCK_BUTTON'] if 'BLOCK_BUTTON' in os.environ else Noneblock_button = int(block_button) if block_button else Noneclass Args(object):def add_argument(self, name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]if arg_type == list:val = val.split()val = arg_type(val)setattr(self, name.lower(), val)return valargs = Args()args.add_argument('UPDATE_COLOR', 'yellow')args.add_argument('QUIET', 0, int)args.add_argument('IGNORE', [], list)args.add_argument('CACHE_UPDATES', 0, int)args.add_argument('FORCE_IPV4', 1, int)def version_in_aur(pkg):p = {'v': '5', 'type': 'search', 'by': 'name', 'arg': pkg}response = requests.get('https://aur.archlinux.org/rpc/', params=p)response = response.json()for r in response['results']:if r['Name'] == pkg:return r['Version']return "NotFound"def vcs_version(pkg, ver):""" Try to find a sensible version for VSC packagesIf pkg looks like a VCS package according tohttps://wiki.archlinux.org/index.php/VCS_package_guidelinestry to extract a sensible (= comparable) version number."""suffices = ['-cvs', '-svn', '-hg', '-darcs', '-bzr', '-git']if not any(pkg.endswith(suffix) for suffix in suffices):# does not look like a VCS packagereturn verif '.r' in ver:# of the form RELEASE.rREVISION: only use the releasereturn ver.split('.r')[0]# no base release to compare, just return Nonereturn Noneif args.force_ipv4:# This is useful, because the AUR API often gets timeouts with# IPV6 and the call does not return.# monkey-patch this function to always return the IPV4-version,# even if capable of IPV6requests.packages.urllib3.util.connection.allowed_gai_family = (lambda: socket.AF_INET)# show the list of updates already cachedif args.cache_updates and block_button in [2, 3]:if '_update_cache' in os.environ:updates = os.environ['_update_cache']else:updates = 'no updates cached'sp.call(['notify-send', 'AUR updates', updates or 'up to date'])# get list of foreign packages -- assumed to be from the AURpackages = sp.check_output(['pacman', '-Qm']).decode('utf8')installed_version = {}for pkg in packages.split('\n'):if not pkg:continuepkg, ver = pkg.split()installed_version[pkg] = verupdates = []for pkg in installed_version.keys():if pkg in args.ignore:continuev_aur = version_in_aur(pkg)v_inst = installed_version[pkg]if vcs_version(pkg, v_aur) != vcs_version(pkg, v_inst):updates.append(pkg + ' (%s -> %s)' % (v_inst, v_aur))# create the message for the blockn_updates = len(updates)msg = ''if n_updates > 0:msg = "<span color='{0}'>{1} AUR updates</span>".format(args.update_color, n_updates)elif not args.quiet:msg = 'AUR up to date'# turn it into a json messagemsg = {'full_text': msg}# cache the new updates listif args.cache_updates:msg['_update_cache'] = '\n'.join(updates)print(json.dumps(msg))# if you don't use caching, show the new list of updatesif not args.cache_updates and block_button in [2, 3]:sp.call(['notify-send', 'AUR updates', '\n'.join(updates) or 'up to date'])if not 'BLOCK_NAME' in os.environ and n_updates > 0:# not called by i3blocks: show the complete listprint('\n'.join(updates))
#!/usr/bin/env python3## Copyright (C) 2017 Marcel Patzwahl# Licensed under the terms of the GNU GPL v3 only.## i3blocks blocklet script to see the available updates of pacman and the AURimport subprocessfrom subprocess import check_outputimport argparseimport osimport redef create_argparse():def _default(name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)strbool = lambda s: s.lower() in ['t', 'true', '1']strlist = lambda s: s.split()parser = argparse.ArgumentParser(description='Check for pacman updates')parser.add_argument('-b','--base_color',default = _default('BASE_COLOR', 'green'),help='base color of the output(default=green)')parser.add_argument('-u','--updates_available_color',default = _default('UPDATE_COLOR', 'yellow'),help='color of the output, when updates are available(default=yellow)')parser.add_argument('-a','--aur',action = 'store_const',const = True,default = _default('AUR', 'False', strbool),help='Include AUR packages. Attn: Yaourt must be installed')parser.add_argument('-y','--aur_yay',action = 'store_const',const = True,default = _default('AUR_YAY', 'False', strbool),help='Include AUR packages. Attn: Yay must be installed')parser.add_argument('-q','--quiet',action = 'store_const',const = True,default = _default('QUIET', 'False', strbool),help = 'Do not produce output when system is up to date')parser.add_argument('-w','--watch',nargs='*',default = _default('WATCH', arg_type=strlist),help='Explicitly watch for specified packages. ''Listed elements are treated as regular expressions for matching.')return parser.parse_args()def get_updates():output = ''try:output = check_output(['checkupdates']).decode('utf-8')except subprocess.CalledProcessError as exc:# checkupdates exits with 2 and no output if no updates are available.# we ignore this case and go onif not (exc.returncode == 2 and not exc.output):raise excif not output:return []updates = [line.split(' ')[0]for line in output.split('\n')if line]return updatesdef get_aur_yaourt_updates():output = ''try:output = check_output(['yaourt', '-Qua']).decode('utf-8')except subprocess.CalledProcessError as exc:# yaourt exits with 1 and no output if no updates are available.# we ignore this case and go onif not (exc.returncode == 1 and not exc.output):raise excif not output:return []aur_updates = [line.split(' ')[0]for line in output.split('\n')if line.startswith('aur/')]return aur_updatesdef get_aur_yay_updates():output = check_output(['yay', '-Qua']).decode('utf-8')if not output:return []aur_updates = [line.split(' ')[0] for line in output.split('\n') if line]return aur_updatesdef matching_updates(updates, watch_list):matches = set()for u in updates:for w in watch_list:if re.match(w, u):matches.add(u)return matcheslabel = os.environ.get("LABEL","")message = "{0}<span color='{1}'>{2}</span>"args = create_argparse()updates = get_updates()if args.aur:updates += get_aur_yaourt_updates()elif args.aur_yay:updates += get_aur_yay_updates()update_count = len(updates)if update_count > 0:if update_count == 1:info = str(update_count) + ' update available'short_info = str(update_count) + ' update'else:info = str(update_count) + ' updates available'short_info = str(update_count) + ' updates'matches = matching_updates(updates, args.watch)if matches:info += ' [{0}]'.format(', '.join(matches))short_info += '*'print(message.format(label, args.updates_available_color, info))print(message.format(label, args.updates_available_color, short_info))elif not args.quiet:print(message.format(label, args.base_color, 'system up to date'))
#!/usr/bin/env python3## Copyright (C) 2017 Marcel Patzwahl# Licensed under the terms of the GNU GPL v3 only.## i3blocks blocklet script to see the available updates of pacman and the AURimport subprocessfrom subprocess import check_outputimport argparseimport osimport redef create_argparse():def _default(name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)strbool = lambda s: s.lower() in ['t', 'true', '1']strlist = lambda s: s.split()parser = argparse.ArgumentParser(description='Check for pacman updates')parser.add_argument('-b','--base_color',default = _default('BASE_COLOR', 'green'),help='base color of the output(default=green)')parser.add_argument('-u','--updates_available_color',default = _default('UPDATE_COLOR', 'yellow'),help='color of the output, when updates are available(default=yellow)')parser.add_argument('-a','--aur',action = 'store_const',const = True,default = _default('AUR', 'False', strbool),help='Include AUR packages. Attn: Yaourt must be installed')parser.add_argument('-y','--aur_yay',action = 'store_const',const = True,default = _default('AUR_YAY', 'False', strbool),help='Include AUR packages. Attn: Yay must be installed')parser.add_argument('-q','--quiet',action = 'store_const',const = True,default = _default('QUIET', 'False', strbool),help = 'Do not produce output when system is up to date')parser.add_argument('-w','--watch',nargs='*',default = _default('WATCH', arg_type=strlist),help='Explicitly watch for specified packages. ''Listed elements are treated as regular expressions for matching.')return parser.parse_args()def get_updates():output = ''try:output = check_output(['checkupdates']).decode('utf-8')except subprocess.CalledProcessError as exc:# checkupdates exits with 2 and no output if no updates are available.# we ignore this case and go onif not (exc.returncode == 2 and not exc.output):raise excif not output:return []updates = [line.split(' ')[0]for line in output.split('\n')if line]return updatesdef get_aur_yaourt_updates():output = ''try:output = check_output(['yaourt', '-Qua']).decode('utf-8')except subprocess.CalledProcessError as exc:# yaourt exits with 1 and no output if no updates are available.# we ignore this case and go onif not (exc.returncode == 1 and not exc.output):raise excif not output:return []aur_updates = [line.split(' ')[0]for line in output.split('\n')if line.startswith('aur/')]return aur_updatesdef get_aur_yay_updates():output = check_output(['yay', '-Qua']).decode('utf-8')if not output:return []aur_updates = [line.split(' ')[0] for line in output.split('\n') if line]return aur_updatesdef matching_updates(updates, watch_list):matches = set()for u in updates:for w in watch_list:if re.match(w, u):matches.add(u)return matcheslabel = os.environ.get("LABEL","")message = "{0}<span color='{1}'>{2}</span>"args = create_argparse()updates = get_updates()if args.aur:updates += get_aur_yaourt_updates()elif args.aur_yay:updates += get_aur_yay_updates()update_count = len(updates)if update_count > 0:if update_count == 1:info = str(update_count) + ' update available'short_info = str(update_count) + ' update'else:info = str(update_count) + ' updates available'short_info = str(update_count) + ' updates'matches = matching_updates(updates, args.watch)if matches:info += ' [{0}]'.format(', '.join(matches))short_info += '*'print(message.format(label, args.updates_available_color, info))print(message.format(label, args.updates_available_color, short_info))elif not args.quiet:print(message.format(label, args.base_color, 'system up to date'))
#!/usr/bin/env bash## Copyright (C) 2015 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to display pending system upgrades# FontAwesome refresh symbol, change if you do not want to install FontAwesomePENDING_SYMBOL=${PENDING_SYMBOL:-"\uf021 "}# By default, show both the symbol and the numbersSYMBOL_ONLY=${SYMBOL_ONLY:-0}# By default, show something when no upgrades are pendingALWAYS_PRINT=${ALWAYS_PRINT:-1}# Colors for when there is/isn't a pending upgradePENDING_COLOR=${PENDING_COLOR:-"#00FF00"}NONPENDING_COLOR=${NONPENDING_COLOR:-"#FFFFFF"}while getopts s:oc:n:Nh opt; docase "$opt" ins) PENDING_SYMBOL="$OPTARG" ;;o) SYMBOL_ONLY=1 ;;c) PENDING_COLOR="$OPTARG" ;;n) NONPENDING_COLOR="$OPTARG" ;;N) ALWAYS_PRINT=0 ;;h) printf \"Usage: apt-upgrades [-s pending_symbol] [-o] [-c pending_color] [-N|-n nonpending_color] [-h]Options:-s\tSpecify a refresh symbol. Default: \"\\\\uf021 \"-o\tShow refresh symbol only, but no numbers.-c\tColor when upgrade is pending. Default: #00FF00-n\tColor when no upgrade is pending. Default: #FFFFFF-N\tOnly display text if upgrade is pending (supercedes -n)-h\tShow this help text\n" && exit 0;;esacdoneread upgraded new removed held < <(aptitude full-upgrade --simulate --assume-yes |\grep -m1 '^[0-9]\+ packages upgraded,' |\tr -cd '0-9 ' |\tr ' ' '\n' |\grep '[0-9]\+' |\xargs echo)if [[ $upgraded != 0 ]] || [[ $new != 0 ]] || [[ $removed != 0 ]] || [[ $held != 0 ]]; thencolor="$PENDING_COLOR"if [[ $SYMBOL_ONLY == 1 ]]; thenecho -e "$PENDING_SYMBOL"echo -e "$PENDING_SYMBOL"elseecho -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"echo -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"fiecho $colorelif [[ $ALWAYS_PRINT == 1 ]]; thencolor="$NONPENDING_COLOR"echo -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"echo -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"echo $colorfi
#!/usr/bin/env bash## Copyright (C) 2015 James Murphy# Licensed under the terms of the GNU GPL v2 only.## i3blocks blocklet script to display pending system upgrades# FontAwesome refresh symbol, change if you do not want to install FontAwesomePENDING_SYMBOL=${PENDING_SYMBOL:-"\uf021 "}# By default, show both the symbol and the numbersSYMBOL_ONLY=${SYMBOL_ONLY:-0}# By default, show something when no upgrades are pendingALWAYS_PRINT=${ALWAYS_PRINT:-1}# Colors for when there is/isn't a pending upgradePENDING_COLOR=${PENDING_COLOR:-"#00FF00"}NONPENDING_COLOR=${NONPENDING_COLOR:-"#FFFFFF"}while getopts s:oc:n:Nh opt; docase "$opt" ins) PENDING_SYMBOL="$OPTARG" ;;o) SYMBOL_ONLY=1 ;;c) PENDING_COLOR="$OPTARG" ;;n) NONPENDING_COLOR="$OPTARG" ;;N) ALWAYS_PRINT=0 ;;h) printf \"Usage: apt-upgrades [-s pending_symbol] [-o] [-c pending_color] [-N|-n nonpending_color] [-h]Options:-s\tSpecify a refresh symbol. Default: \"\\\\uf021 \"-o\tShow refresh symbol only, but no numbers.-c\tColor when upgrade is pending. Default: #00FF00-n\tColor when no upgrade is pending. Default: #FFFFFF-N\tOnly display text if upgrade is pending (supercedes -n)-h\tShow this help text\n" && exit 0;;esacdoneread upgraded new removed held < <(aptitude full-upgrade --simulate --assume-yes |\grep -m1 '^[0-9]\+ packages upgraded,' |\tr -cd '0-9 ' |\tr ' ' '\n' |\grep '[0-9]\+' |\xargs echo)if [[ $upgraded != 0 ]] || [[ $new != 0 ]] || [[ $removed != 0 ]] || [[ $held != 0 ]]; thencolor="$PENDING_COLOR"if [[ $SYMBOL_ONLY == 1 ]]; thenecho -e "$PENDING_SYMBOL"echo -e "$PENDING_SYMBOL"elseecho -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"echo -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"fiecho $colorelif [[ $ALWAYS_PRINT == 1 ]]; thencolor="$NONPENDING_COLOR"echo -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"echo -e "$PENDING_SYMBOL$upgraded/$new/$removed/$held"echo $colorfi
#!/usr/bin/env python3# -*- coding: utf-8 -*-# Copyright © 2019 Kudlaty 01 <kudlok@mail.ru># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import getopt, requests, urllib, yaml, sys, osgconfig = {'apikey': 'example_api_key','installationId': 2955,# uncomment if lat/long is preferred instead of sensorId# 'lat': '',# 'lng': ''}class AirlyApiClient:def __init__(self, config=None):"""init with optionally config"""self.config = config or self.parseConfig(self.parseInstance())self.apiUrl = 'https://airapi.airly.eu/v2/measurements/%s?' % ('installation' if 'installationId' in self.config else 'point')def parseInstance(self):""" parse the instance environment variable """instance = ''try:instance = os.environ['BLOCK_INSTANCE']except KeyError:return Nonefinally:if len(instance):return instancereturn Nonedef parseConfig(self, instance):"""parse the instance-specific config file or a default one"""_instance = instance or self.parseInstance()xdgHome = os.environ['XDG_CONFIG_HOME'] or os.environ['HOME'] + '/.config'configPath = xdgHome + '/i3blocks-airly/%s.yml' % (_instance or 'config')try:with open(configPath, 'r') as stream:config=yaml.load(stream)return configexcept:global gconfigreturn gconfigdef getMeasurement(self, config=None):"""get the measurements for the place"""cfg = config or self.configr = requests.get(self.apiUrl + urllib.parse.urlencode(self.config))self.lastResult = r.json()return self.lastResultdef getCurrentMeasurement(self, measurement=None):"""get only the current measurement"""m = measurement or self.getMeasurement()return m['current']['indexes']def getCaqiMeasurement(self, measurement=None):"""get only the current CAQUI measurement"""m = measurement or self.getCurrentMeasurement()caqi=next(c for c in m if c['name'] == 'AIRLY_CAQI')return caqidef getAirQualityIndex(self, caqiMeasurement=None):"""get the air quality index value from given CAQI measurementit's current measuement by default"""m = caqiMeasurement or self.getCaqiMeasurement()index = m['value']return indexdef getColor(self, measurement=None):"""get color for given air quality indes"""m = measurement or self.getCaqiMeasurement()return m['color']def displayResult(self,jsonData=None):"""display the measurement result"""result = self.getAirQualityIndex()print(round(result,2))print(round(result))print(self.getColor())def main(argv):args=argvclient = AirlyApiClient()client.displayResult()if __name__ == "__main__":main(sys.argv[1:])
#!/usr/bin/env python3# -*- coding: utf-8 -*-# Copyright © 2019 Kudlaty 01 <kudlok@mail.ru># This program 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.# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import getopt, requests, urllib, yaml, sys, osgconfig = {'apikey': 'example_api_key','installationId': 2955,# uncomment if lat/long is preferred instead of sensorId# 'lat': '',# 'lng': ''}class AirlyApiClient:def __init__(self, config=None):"""init with optionally config"""self.config = config or self.parseConfig(self.parseInstance())self.apiUrl = 'https://airapi.airly.eu/v2/measurements/%s?' % ('installation' if 'installationId' in self.config else 'point')def parseInstance(self):""" parse the instance environment variable """instance = ''try:instance = os.environ['BLOCK_INSTANCE']except KeyError:return Nonefinally:if len(instance):return instancereturn Nonedef parseConfig(self, instance):"""parse the instance-specific config file or a default one"""_instance = instance or self.parseInstance()xdgHome = os.environ['XDG_CONFIG_HOME'] or os.environ['HOME'] + '/.config'configPath = xdgHome + '/i3blocks-airly/%s.yml' % (_instance or 'config')try:with open(configPath, 'r') as stream:config=yaml.load(stream)return configexcept:global gconfigreturn gconfigdef getMeasurement(self, config=None):"""get the measurements for the place"""cfg = config or self.configr = requests.get(self.apiUrl + urllib.parse.urlencode(self.config))self.lastResult = r.json()return self.lastResultdef getCurrentMeasurement(self, measurement=None):"""get only the current measurement"""m = measurement or self.getMeasurement()return m['current']['indexes']def getCaqiMeasurement(self, measurement=None):"""get only the current CAQUI measurement"""m = measurement or self.getCurrentMeasurement()caqi=next(c for c in m if c['name'] == 'AIRLY_CAQI')return caqidef getAirQualityIndex(self, caqiMeasurement=None):"""get the air quality index value from given CAQI measurementit's current measuement by default"""m = caqiMeasurement or self.getCaqiMeasurement()index = m['value']return indexdef getColor(self, measurement=None):"""get color for given air quality indes"""m = measurement or self.getCaqiMeasurement()return m['color']def displayResult(self,jsonData=None):"""display the measurement result"""result = self.getAirQualityIndex()print(round(result,2))print(round(result))print(self.getColor())def main(argv):args=argvclient = AirlyApiClient()client.displayResult()if __name__ == "__main__":main(sys.argv[1:])
#!/usr/bin/env python3# Show usage information for an AFS directory.# Copyright 2017 Johannes Lange## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import argparseimport osimport subprocess as spdef _default(name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)parser = argparse.ArgumentParser(description='Get AFS quota and usage information.',formatter_class=argparse.ArgumentDefaultsHelpFormatter,)parser.add_argument('-c', '--critical', type=int, default=_default('CRITICAL', 90, int),help='Critical usage percentage.')parser.add_argument('-fg', '--fg-color', type=str, default=_default('CRIT_FG_COLOR', "#FF0000"),help='Foreground color for critical usage.')parser.add_argument('-bg', '--bg-color', type=str, default=_default('CRIT_BG_COLOR', ''),help='Background color for critical usage.')args = parser.parse_args()# set the afs directory to be checkeddirectory = os.environ.get('BLOCK_INSTANCE', '~/afs/')label = os.environ.get('LABEL', '')# expand environment variables etc.directory = os.path.expandvars(directory)directory = os.path.expanduser(directory)fs_output = sp.check_output(['fs', 'lq', '-human', directory],universal_newlines=True)# second line contains the informationfs_output = fs_output.split('\n')[1]quota, used, percentage = fs_output.split()[1:4]percentage = int(percentage.split('%')[0])output = '%s%s/%s (%i%%)' % (label, used, quota, percentage)if percentage >= args.critical:if args.bg_color:output = "<span color='%s' bgcolor='%s'>%s</span>" %\(args.fg_color, args.bg_color, output)else:output = "<span color='%s'>%s</span>" % (args.fg_color, output)print(output)
#!/usr/bin/env python3# Show usage information for an AFS directory.# Copyright 2017 Johannes Lange## This program 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.## This program 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 this program. If not, see <http://www.gnu.org/licenses/>.import argparseimport osimport subprocess as spdef _default(name, default='', arg_type=str):val = defaultif name in os.environ:val = os.environ[name]return arg_type(val)parser = argparse.ArgumentParser(description='Get AFS quota and usage information.',formatter_class=argparse.ArgumentDefaultsHelpFormatter,)parser.add_argument('-c', '--critical', type=int, default=_default('CRITICAL', 90, int),help='Critical usage percentage.')parser.add_argument('-fg', '--fg-color', type=str, default=_default('CRIT_FG_COLOR', "#FF0000"),help='Foreground color for critical usage.')parser.add_argument('-bg', '--bg-color', type=str, default=_default('CRIT_BG_COLOR', ''),help='Background color for critical usage.')args = parser.parse_args()# set the afs directory to be checkeddirectory = os.environ.get('BLOCK_INSTANCE', '~/afs/')label = os.environ.get('LABEL', '')# expand environment variables etc.directory = os.path.expandvars(directory)directory = os.path.expanduser(directory)fs_output = sp.check_output(['fs', 'lq', '-human', directory],universal_newlines=True)# second line contains the informationfs_output = fs_output.split('\n')[1]quota, used, percentage = fs_output.split()[1:4]percentage = int(percentage.split('%')[0])output = '%s%s/%s (%i%%)' % (label, used, quota, percentage)if percentage >= args.critical:if args.bg_color:output = "<span color='%s' bgcolor='%s'>%s</span>" %\(args.fg_color, args.bg_color, output)else:output = "<span color='%s'>%s</span>" % (args.fg_color, output)print(output)
# This file has been auto-generated by i3-config-wizard(1).# It will not be overwritten, so edit it as you like.## Should you change your keyboard layout some time, delete# this file and re-run i3-config-wizard(1).## i3 config file (v4)## Please see http://i3wm.org/docs/userguide.html for a complete reference!set $mod Mod4set $term $(command -v kitty || command -v urxvt || command -v xterm || command -v xst || command -v st)# Font for window titles. Will also be used by the bar unless a different font# is used in the bar {} block below.font pango:Hasklig 0# This font is widely installed, provides lots of unicode glyphs, right-to-left# text rendering and scalability on retina/hidpi displays (thanks to pango).#font pango:DejaVu Sans Mono 9# Before i3 v4.8, we used to recommend this one as the default:# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1# The font above is very space-efficient, that is, it looks good, sharp and# clear in small sizes. However, its unicode glyph coverage is limited, the old# X core fonts rendering does not support right-to-left and this being a bitmap# font, it doesn’t scale on retina/hidpi displays.# Use Mouse+$mod to drag floating windows to their wanted positionfloating_modifier $mod# start a terminalbindsym $mod+Return exec $term# kill focused windowbindsym $mod+Shift+q kill# start dmenu / rofi (a program launcher)# bindsym $mod+d exec dmenu_runbindsym $mod+d exec rofi -show runbindsym $mod+Shift+d exec rofi -show drun# There also is the (new) i3-dmenu-desktop which only displays applications# shipping a .desktop file. It is a wrapper around dmenu, so you need that# installed.# bindsym $mod+d exec --no-startup-id i3-dmenu-desktop# run an arbitrary shell sommandbindsym $mod+Shift+Return exec rofi -dmenu -p ">" | $SHELLbindsym $mod+Tab exec --no-startup-id rofi -show window# change focusbindsym $mod+h focus leftbindsym $mod+j focus downbindsym $mod+k focus upbindsym $mod+l focus right# move focused windowbindsym $mod+Shift+h move left 12 pxbindsym $mod+Shift+j move down 12 pxbindsym $mod+Shift+k move up 12 pxbindsym $mod+Shift+l move right 12 px# split in horizontal orientationbindsym $mod+Shift+v split h# split in vertical orientationbindsym $mod+v split v# toggle fullscreen mode for the focused containerbindsym $mod+f fullscreen toggle# change container layout (stacked, tabbed, toggle split)#bindsym $mod+s layout stackingbindsym $mod+w layout tabbedbindsym $mod+e layout toggle split# toggle tiling / floatingbindsym $mod+Shift+space floating toggle# change focus between tiling / floating windowsbindsym $mod+space focus mode_toggle# Move floating container to the centerbindsym $mod+c move position centerbindsym $mod+shift+c move position center#bindsym $mod+shift+c move absolute position center# focus last urgentbindsym $mod+i [urgent=latest] focus# focus the parent containerbindsym $mod+a focus parent# focus the child containerbindsym $mod+x focus child# switch to workspacebindsym $mod+n workspace next_on_outputbindsym $mod+p workspace prev_on_outputbindsym $mod+1 workspace 1bindsym $mod+2 workspace 2bindsym $mod+3 workspace 3bindsym $mod+4 workspace 4bindsym $mod+5 workspace 5bindsym $mod+6 workspace 6bindsym $mod+7 workspace 7bindsym $mod+8 workspace 8bindsym $mod+9 workspace 9bindsym $mod+0 workspace 10bindsym $mod+z scratchpad show# move focused container to workspacebindsym $mod+Shift+n move container to workspace next_on_output , workspace next_on_outputbindsym $mod+Shift+p move container to workspace prev_on_output , workspace prev_on_outputbindsym $mod+shift+1 exec "i3-msg move container to workspace 1 && i3-msg workspace 1"bindsym $mod+shift+2 exec "i3-msg move container to workspace 2 && i3-msg workspace 2"bindsym $mod+shift+3 exec "i3-msg move container to workspace 3 && i3-msg workspace 3"bindsym $mod+shift+4 exec "i3-msg move container to workspace 4 && i3-msg workspace 4"bindsym $mod+shift+5 exec "i3-msg move container to workspace 5 && i3-msg workspace 5"bindsym $mod+shift+6 exec "i3-msg move container to workspace 6 && i3-msg workspace 6"bindsym $mod+shift+7 exec "i3-msg move container to workspace 7 && i3-msg workspace 7"bindsym $mod+shift+8 exec "i3-msg move container to workspace 8 && i3-msg workspace 8"bindsym $mod+shift+9 exec "i3-msg move container to workspace 9 && i3-msg workspace 9"bindsym $mod+shift+0 exec "i3-msg move container to workspace 10 && i3-msg workspace 10"bindsym $mod+Shift+z move scratchpad# move focus to outputbindsym $mod+o focus output nextbindsym $mod+shift+o move container to output next , focus output nextbindsym $mod+shift+w move workspace to output nextbindsym $mod+shift+s sticky togglefocus_follows_mouse no# windows demanding focus will always be marked urgent but the focus will not be stolenfocus_on_window_activation urgent# reload the configuration filebindsym $mod+Shift+r reload# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)bindsym $mod+Shift+Escape restart# exit i3 (logs you out of your X session)bindsym $mod+Shift+e exec "echo 'no\nyes' | rofi -dmenu -p 'exit i3?' | grep -qi yes && i3-msg exit"# resize window (you can also use the mouse for that)mode "resize" {# These bindings trigger as soon as you enter the resize mode# border pixel 6, border color #FF0000# Pressing left will shrink the window’s width.bindsym Shift+h resize shrink width 12 px, move right 6 pxbindsym h resize shrink width 192 px, move right 96 px# Pressing up will shrink the window’s height.bindsym Shift+k resize grow height 12 px, move up 6 pxbindsym k resize grow height 192 px, move up 96 px# Pressing down will grow the window’s height.bindsym Shift+j resize shrink height 12 px, move down 6 pxbindsym j resize shrink height 192 px, move down 96 px# Pressing right will grow the window’s width.bindsym Shift+l resize grow width 12 px, move left 6 pxbindsym l resize grow width 192 px, move left 96 px# same bindings, but for the arrow keysbindsym Left resize shrink width 12 px, move right 6 pxbindsym Up resize grow height 12 px, move up 6 pxbindsym Down resize shrink height 12 px, move down 6 pxbindsym Right resize grow width 12 px, move left 6 px# make also center work in resize modebindsym $mod+shift+c move absolute position centerbindsym Shift+c move position centerbindsym c move position center# back to normal: Enter or Escapebindsym Return mode "default"bindsym Escape mode "default"bindsym $mod+r mode "default"# move focused windowbindsym $mod+Shift+h move leftbindsym $mod+Shift+j move downbindsym $mod+Shift+k move upbindsym $mod+Shift+l move right# alternatively, you can use the cursor keys:bindsym $mod+Shift+Left move leftbindsym $mod+Shift+Down move downbindsym $mod+Shift+Up move upbindsym $mod+Shift+Right move right}bindsym $mod+r mode "resize"# resizingset $maxw 1644set $minw 12set $maxh 1236set $minh 12# floating window sizefloating_minimum_size 12 x 12floating_maximum_size 1644 x 1236# Pressing left will shrink the window’s width.bindsym $mod+Shift+Left resize shrink width 24 px, move right 12 pxbindsym $mod+Left resize shrink width 96 px, move right 48 px# Pressing up will grow the window’s height.bindsym $mod+Shift+Up resize grow height 24 px, move up 12 pxbindsym $mod+Up resize grow height 96 px, move up 48 px# Pressing down will shrink the window’s height.bindsym $mod+Shift+Down resize shrink height 24 px, move down 12 pxbindsym $mod+Down resize shrink height 96 px, move down 48 px# Pressing right will grow the window’s width.bindsym $mod+Shift+Right resize grow width 24 px, move left 12 pxbindsym $mod+Right resize grow width 96 px, move left 48 pxset $black #191919set $dark #222222set $tone #66ccccset $dimmed #747369set $attention #c47848# window colors# border background text indicator child_borderclient.focused $dimmed $dimmed $tone $dimmed $dimmedclient.focused_tab_title $dimmed $dimmed $blackclient.focused_inactive $black $dark $dimmed $dark $blackclient.unfocused $black $black $dimmed $black $blackclient.urgent $attention $attention $black $attention $attention# Start i3bar to display a workspace bar (plus the system information i3status# finds out, if available)bar {mode invisiblemodifier Noneposition topstatus_command i3blockstray_output primary# tray_padding 0separator_symbol " "font pango:Hasklig, Source Code Pro 7colors {background $darkseparator #757575# border background textfocused_workspace $dark $dark $toneinactive_workspace $dark $dark $dimmedurgent_workspace $attention $attention $tone}}# i3barbindsym $mod+b bar mode dockbindsym $mod+shift+b bar mode invisible# gapsbindsym $mod+g gaps inner all set 0pxbindsym $mod+shift+g gaps inner all set 12px# borderbindsym $mod+t exec i3-msg '[class=".*"] border pixel 1'bindsym $mod+shift+t exec i3-msg '[class=".*"] border none'# default_borderdefault_border pixel 1default_floating_border pixel 1# Media volume controlsbindsym XF86AudioMute exec amixer set Master togglebindsym XF86AudioLowerVolume exec amixer set Master 2%-bindsym XF86AudioRaiseVolume exec amixer set Master 2%+bindsym XF86MonBrightnessUp exec brightnessctl s +10%bindsym XF86MonBrightnessDown exec brightnessctl s 10%-bindsym XF86AudioPlay exec playerctl play-pausebindsym XF86AudioNext exec playerctl nextbindsym XF86AudioPrev exec playerctl previousbindsym XF86AudioStop exec playerctl play-pause# Screenshotbindsym $mod+s exec "maim -s -u --quality=10 | xclip -selection clipboard -t image/png"# # repeat key rateexec xset r rate 260 90 # use /etc/X11/xorg.conf.d# x configexec xrdb -load .Xresources# bg colorexec --no-startup-id hsetroot -solid "#000000"# center new floating windowsfor_window [floating] move position center# float pop-ups, don't focusno_focus [window_role="pop-up"]for_window [window_role="pop-up"] floating enablefor_window [window_role="^floating$"] floating enable# float alwaysfor_window [class="Sxiv"] floating enablefor_window [class="Nsxiv"] floating enablefor_window [class="Vlc"] floating enablefor_window [class="kitty"] floating enable , resize set 828 420for_window [class="xst"] floating enable , resize set 828 420 , border pixel 1for_window [class="XTerm"] floating enable , resize set 828 420for_window [class="URxvt"] floating enable , resize set 828 420# for_window [class="Vimb"] floating enable# default layout for workspace level windowsworkspace_layout tabbed# set audioexec --no-startup-id pipewire# set default keyboard layoutexec --no-startup-id setxkbmap -layout us -variant symbolic -option 'compose:off'# change keyboard layoutbindsym $mod+backslash exec setxkbmap -layout us -variant symbolic -option 'compose:off'bindsym $mod+shift+backslash exec setxkbmap us intl# night light#exec --no-startup-id xflux -l 41.1 -g -8.4 -k 2500exec --no-startup-id redshift -l 41.1:-8.4 -t 6500:2500# start compositorexec --no-startup-id picom# # hdmi mirror# exec --no-startup-id xrandr --output HDMI-1 --same-as eDP-1# bg imageexec --no-startup-id feh --bg-fill ~/.jrvieira/bg.png# rebind caps to escexec --no-startup-id xmodmap ~/.Xmodmap# hide cursorexec xbanish# notificationsexec dunst# machine specificexec --no-startup-id ~/this# catexec oneko -tofocus# launch terminal# exec $term
# This file has been auto-generated by i3-config-wizard(1).# It will not be overwritten, so edit it as you like.## Should you change your keyboard layout some time, delete# this file and re-run i3-config-wizard(1).## i3 config file (v4)## Please see http://i3wm.org/docs/userguide.html for a complete reference!set $mod Mod4set $term $(command -v kitty || command -v urxvt || command -v xterm || command -v xst || command -v st)# Font for window titles. Will also be used by the bar unless a different font# is used in the bar {} block below.font pango:Hasklig 0# This font is widely installed, provides lots of unicode glyphs, right-to-left# text rendering and scalability on retina/hidpi displays (thanks to pango).#font pango:DejaVu Sans Mono 9# Before i3 v4.8, we used to recommend this one as the default:# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1# The font above is very space-efficient, that is, it looks good, sharp and# clear in small sizes. However, its unicode glyph coverage is limited, the old# X core fonts rendering does not support right-to-left and this being a bitmap# font, it doesn’t scale on retina/hidpi displays.# Use Mouse+$mod to drag floating windows to their wanted positionfloating_modifier $mod# start a terminalbindsym $mod+Return exec $term# kill focused windowbindsym $mod+Shift+q kill# start dmenu / rofi (a program launcher)# bindsym $mod+d exec dmenu_runbindsym $mod+d exec rofi -show runbindsym $mod+Shift+d exec rofi -show drun# There also is the (new) i3-dmenu-desktop which only displays applications# shipping a .desktop file. It is a wrapper around dmenu, so you need that# installed.# bindsym $mod+d exec --no-startup-id i3-dmenu-desktop# run an arbitrary shell sommandbindsym $mod+Shift+Return exec rofi -dmenu -p ">" | $SHELLbindsym $mod+Tab exec --no-startup-id rofi -show window# change focusbindsym $mod+h focus leftbindsym $mod+j focus downbindsym $mod+k focus upbindsym $mod+l focus right# move focused windowbindsym $mod+Shift+h move left 12 pxbindsym $mod+Shift+j move down 12 pxbindsym $mod+Shift+k move up 12 pxbindsym $mod+Shift+l move right 12 px# split in horizontal orientationbindsym $mod+Shift+v split h# split in vertical orientationbindsym $mod+v split v# toggle fullscreen mode for the focused containerbindsym $mod+f fullscreen toggle# change container layout (stacked, tabbed, toggle split)#bindsym $mod+s layout stackingbindsym $mod+w layout tabbedbindsym $mod+e layout toggle split# toggle tiling / floatingbindsym $mod+Shift+space floating toggle# change focus between tiling / floating windowsbindsym $mod+space focus mode_toggle# Move floating container to the centerbindsym $mod+c move position centerbindsym $mod+shift+c move position center#bindsym $mod+shift+c move absolute position center# focus last urgentbindsym $mod+i [urgent=latest] focus# focus the parent containerbindsym $mod+a focus parent# focus the child containerbindsym $mod+x focus child# switch to workspacebindsym $mod+n workspace next_on_outputbindsym $mod+p workspace prev_on_outputbindsym $mod+1 workspace 1bindsym $mod+2 workspace 2bindsym $mod+3 workspace 3bindsym $mod+4 workspace 4bindsym $mod+5 workspace 5bindsym $mod+6 workspace 6bindsym $mod+7 workspace 7bindsym $mod+8 workspace 8bindsym $mod+9 workspace 9bindsym $mod+0 workspace 10bindsym $mod+z scratchpad show# move focused container to workspacebindsym $mod+Shift+n move container to workspace next_on_output , workspace next_on_outputbindsym $mod+Shift+p move container to workspace prev_on_output , workspace prev_on_outputbindsym $mod+shift+1 exec "i3-msg move container to workspace 1 && i3-msg workspace 1"bindsym $mod+shift+2 exec "i3-msg move container to workspace 2 && i3-msg workspace 2"bindsym $mod+shift+3 exec "i3-msg move container to workspace 3 && i3-msg workspace 3"bindsym $mod+shift+4 exec "i3-msg move container to workspace 4 && i3-msg workspace 4"bindsym $mod+shift+5 exec "i3-msg move container to workspace 5 && i3-msg workspace 5"bindsym $mod+shift+6 exec "i3-msg move container to workspace 6 && i3-msg workspace 6"bindsym $mod+shift+7 exec "i3-msg move container to workspace 7 && i3-msg workspace 7"bindsym $mod+shift+8 exec "i3-msg move container to workspace 8 && i3-msg workspace 8"bindsym $mod+shift+9 exec "i3-msg move container to workspace 9 && i3-msg workspace 9"bindsym $mod+shift+0 exec "i3-msg move container to workspace 10 && i3-msg workspace 10"bindsym $mod+Shift+z move scratchpad# move focus to outputbindsym $mod+o focus output nextbindsym $mod+shift+o move container to output next , focus output nextbindsym $mod+shift+w move workspace to output nextbindsym $mod+shift+s sticky togglefocus_follows_mouse no# windows demanding focus will always be marked urgent but the focus will not be stolenfocus_on_window_activation urgent# reload the configuration filebindsym $mod+Shift+r reload# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)bindsym $mod+Shift+Escape restart# exit i3 (logs you out of your X session)bindsym $mod+Shift+e exec "echo 'no\nyes' | rofi -dmenu -p 'exit i3?' | grep -qi yes && i3-msg exit"# resize window (you can also use the mouse for that)mode "resize" {# These bindings trigger as soon as you enter the resize mode# border pixel 6, border color #FF0000# Pressing left will shrink the window’s width.bindsym Shift+h resize shrink width 12 px, move right 6 pxbindsym h resize shrink width 192 px, move right 96 px# Pressing up will shrink the window’s height.bindsym Shift+k resize grow height 12 px, move up 6 pxbindsym k resize grow height 192 px, move up 96 px# Pressing down will grow the window’s height.bindsym Shift+j resize shrink height 12 px, move down 6 pxbindsym j resize shrink height 192 px, move down 96 px# Pressing right will grow the window’s width.bindsym Shift+l resize grow width 12 px, move left 6 pxbindsym l resize grow width 192 px, move left 96 px# same bindings, but for the arrow keysbindsym Left resize shrink width 12 px, move right 6 pxbindsym Up resize grow height 12 px, move up 6 pxbindsym Down resize shrink height 12 px, move down 6 pxbindsym Right resize grow width 12 px, move left 6 px# make also center work in resize modebindsym $mod+shift+c move absolute position centerbindsym Shift+c move position centerbindsym c move position center# back to normal: Enter or Escapebindsym Return mode "default"bindsym Escape mode "default"bindsym $mod+r mode "default"# move focused windowbindsym $mod+Shift+h move leftbindsym $mod+Shift+j move downbindsym $mod+Shift+k move upbindsym $mod+Shift+l move right# alternatively, you can use the cursor keys:bindsym $mod+Shift+Left move leftbindsym $mod+Shift+Down move downbindsym $mod+Shift+Up move upbindsym $mod+Shift+Right move right}bindsym $mod+r mode "resize"# resizingset $maxw 1644set $minw 12set $maxh 1236set $minh 12# floating window sizefloating_minimum_size 12 x 12floating_maximum_size 1644 x 1236# Pressing left will shrink the window’s width.bindsym $mod+Shift+Left resize shrink width 24 px, move right 12 pxbindsym $mod+Left resize shrink width 96 px, move right 48 px# Pressing up will grow the window’s height.bindsym $mod+Shift+Up resize grow height 24 px, move up 12 pxbindsym $mod+Up resize grow height 96 px, move up 48 px# Pressing down will shrink the window’s height.bindsym $mod+Shift+Down resize shrink height 24 px, move down 12 pxbindsym $mod+Down resize shrink height 96 px, move down 48 px# Pressing right will grow the window’s width.bindsym $mod+Shift+Right resize grow width 24 px, move left 12 pxbindsym $mod+Right resize grow width 96 px, move left 48 pxset $black #191919set $dark #222222set $tone #66ccccset $dimmed #747369set $attention #c47848# window colors# border background text indicator child_borderclient.focused $dimmed $dimmed $tone $dimmed $dimmedclient.focused_tab_title $dimmed $dimmed $blackclient.focused_inactive $black $dark $dimmed $dark $blackclient.unfocused $black $black $dimmed $black $blackclient.urgent $attention $attention $black $attention $attention# Start i3bar to display a workspace bar (plus the system information i3status# finds out, if available)bar {mode invisiblemodifier Noneposition topstatus_command i3blockstray_output primary# tray_padding 0separator_symbol " "font pango:Hasklig, Source Code Pro 7colors {background $darkseparator #757575# border background textfocused_workspace $dark $dark $toneinactive_workspace $dark $dark $dimmedurgent_workspace $attention $attention $tone}}# i3barbindsym $mod+b bar mode dockbindsym $mod+shift+b bar mode invisible# gapsbindsym $mod+g gaps inner all set 0pxbindsym $mod+shift+g gaps inner all set 12px# borderbindsym $mod+t exec i3-msg '[class=".*"] border pixel 1'bindsym $mod+shift+t exec i3-msg '[class=".*"] border none'# default_borderdefault_border pixel 1default_floating_border pixel 1# Media volume controlsbindsym XF86AudioMute exec amixer set Master togglebindsym XF86AudioLowerVolume exec amixer set Master 2%-bindsym XF86AudioRaiseVolume exec amixer set Master 2%+bindsym XF86MonBrightnessUp exec brightnessctl s +10%bindsym XF86MonBrightnessDown exec brightnessctl s 10%-bindsym XF86AudioPlay exec playerctl play-pausebindsym XF86AudioNext exec playerctl nextbindsym XF86AudioPrev exec playerctl previousbindsym XF86AudioStop exec playerctl play-pause# Screenshotbindsym $mod+s exec "maim -s -u --quality=10 | xclip -selection clipboard -t image/png"# # repeat key rateexec xset r rate 260 90 # use /etc/X11/xorg.conf.d# x configexec xrdb -load .Xresources# bg colorexec --no-startup-id hsetroot -solid "#000000"# center new floating windowsfor_window [floating] move position center# float pop-ups, don't focusno_focus [window_role="pop-up"]for_window [window_role="pop-up"] floating enablefor_window [window_role="^floating$"] floating enable# float alwaysfor_window [class="Sxiv"] floating enablefor_window [class="Nsxiv"] floating enablefor_window [class="Vlc"] floating enablefor_window [class="kitty"] floating enable , resize set 828 420for_window [class="xst"] floating enable , resize set 828 420 , border pixel 1for_window [class="XTerm"] floating enable , resize set 828 420for_window [class="URxvt"] floating enable , resize set 828 420# for_window [class="Vimb"] floating enable# default layout for workspace level windowsworkspace_layout tabbed# set audioexec --no-startup-id pipewire# set default keyboard layoutexec --no-startup-id setxkbmap -layout us -variant symbolic -option 'compose:off'# change keyboard layoutbindsym $mod+backslash exec setxkbmap -layout us -variant symbolic -option 'compose:off'bindsym $mod+shift+backslash exec setxkbmap us intl# night light#exec --no-startup-id xflux -l 41.1 -g -8.4 -k 2500exec --no-startup-id redshift -l 41.1:-8.4 -t 6500:2500# start compositorexec --no-startup-id picom# # hdmi mirror# exec --no-startup-id xrandr --output HDMI-1 --same-as eDP-1# bg imageexec --no-startup-id feh --bg-fill ~/.jrvieira/bg.png# rebind caps to escexec --no-startup-id xmodmap ~/.Xmodmap# hide cursorexec xbanish# notificationsexec dunst# machine specificexec --no-startup-id ~/this# catexec oneko -tofocus# launch terminal# exec $term
if [ -z "$DISPLAY" ] && [ -n "$XDG_VTNR" ] && [ "$XDG_VTNR" -eq 1 ]; thenexec startxfi[ -z "$PS1" ] && return. .bashrcif [[ $TERM == xterm-termite ]]; then. /etc/profile.d/vte.sh__vte_prompt_commandfiexport PATH="$HOME/.local/bin:$PATH"#source /home/zero/.config/broot/launcher/bash/brexport PATH=/usr/local/node-v20.15.1/bin:$PATH. "$HOME/.cargo/env"
*VT100*colorMode: on*VT100*dynamicColors: onXft.antialias: trueXft.hinting: trueXft.hintstyle: hintslightXft.rgba: rgbXft.dpi: 96! special*.foreground: #d0d0d0*.background: #222222*.cursorColor: #79d4d5! black*.color0: #191919*.color8: #747369! red*.color1: #f2777a*.color9: #913535! green*.color2: #99cc99*.color10: #A0A35D! yellow*.color3: #ffcc66*.color11: #C47848! blue*.color4: #6699cc*.color12: #527386! magenta*.color5: #cc99cc*.color13: #846488! cyan*.color6: #66cccc*.color14: #618E8B! white*.color7: #ffffff*.color15: #969896*.selection_background: #79d4d5*.selection_foreground: #000000Xcursor.size: 22!xtermXTerm.termName: xterm-256colorXTerm*utf8: 1!XTerm*faceName: Source Code Pro - BlackXTerm*faceName: SauceCodePro Nerd Font MonoXTerm*metaSendsEscape: trueXTerm*faceSize: 7XTerm*cursor: i-beamXTerm*visualBell: falseXTerm*cursorColor: #79d4d5XTerm*cursorBlink: trueXTerm*toolBar: falseXTerm*internalBorder: 20XTerm*borderWidth: 0XTerm*loginShell: trueXTerm*scrollBar: falseXTerm*rightScrollBar: falseXTerm*saveLines: 999!XTerm*selectToClipboard: true! enable OSC 52 clipboard supportXTerm.vt100.allowWindowOps: trueXTerm.vt100.disallowedWindowOps: 20,21,SetXprop!XTerm.vt100.selectToClipboard: true! urxvtURxvt*internalBorder: 20URxvt*buffered: trueURxvt*jumpScroll: trueURxvt*skipScroll: trueURxvt*visualBell: falseURxvt*cursorColor: #79d4d5URxvt*cursorBlink: trueURxvt.underlineURLs: falseURxvt*font: xft:Source Code Pro - Black:size=7URxvt.letterSpace: -1URxvt.lineSpace: 0URxvt*depth: 32URxvt*borderless: trueURxvt*scrollBar: falseURxvt*loginShell: trueURxvt*secondaryScroll: true # Enable Shift-PageUp/Down in screenURxvt*saveLines: 5000URxvt*termName: rxvt-unicode-256colorURxvt.keysym.Shift-Control-V: eval:paste_clipboardURxvt.keysym.Shift-Control-C: eval:selection_to_clipboardURxvt.iso14755: falseURxvt.iso14755_52: false! xstst.borderless: 1st.font: Source Code Pro:pixelsize=9:antialias=true:autohint=true;st.borderpx: 20st.cursorblinkontype: 0st.blinktimeout: 300