aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPascal Dulieu <pascal@dulieu.uk>2025-07-30 11:45:00 +0100
committerPascal Dulieu <pascal@dulieu.uk>2025-07-30 11:45:00 +0100
commitc19fa68472bec357914ff264e52b45945221d530 (patch)
tree8bb993d3f9bf7b91155300fcc7fe1b282faf7066
-rw-r--r--.config/nvim/.gitignore8
-rw-r--r--.config/nvim/.neoconf.json15
-rw-r--r--.config/nvim/LICENSE201
-rw-r--r--.config/nvim/README.md4
-rw-r--r--.config/nvim/colors/lushwal.vim218
-rw-r--r--.config/nvim/init.lua2
-rw-r--r--.config/nvim/lazy-lock.json38
-rw-r--r--.config/nvim/lazyvim.json10
-rw-r--r--.config/nvim/lua/config/autocmds.lua8
-rw-r--r--.config/nvim/lua/config/keymaps.lua3
-rw-r--r--.config/nvim/lua/config/lazy.lua53
-rw-r--r--.config/nvim/lua/config/options.lua6
-rw-r--r--.config/nvim/lua/plugins/example.lua197
-rw-r--r--.config/nvim/lua/plugins/lushwal.lua119
-rw-r--r--.config/nvim/stylua.toml3
-rw-r--r--.config/tmux-powerline/config.sh469
-rw-r--r--.config/tmux-powerline/themes/main.sh230
-rw-r--r--.gitignore4
-rw-r--r--.gitmodules33
-rw-r--r--.irssi/config331
-rw-r--r--.irssi/default.theme295
-rw-r--r--.irssi/neongold.theme206
-rw-r--r--.irssi/pipeline.theme270
-rw-r--r--.irssi/scripts/adv_windowlist.pl2988
-rw-r--r--.irssi/scripts/mouse.pl168
-rw-r--r--.irssi/scripts/nm2.pl569
-rw-r--r--.irssi/scripts/tmux-nicklist-portable.pl432
m---------.oh-my-zsh/custom/plugins/zsh-autocomplete0
m---------.oh-my-zsh/custom/plugins/zsh-autosuggestions0
m---------.oh-my-zsh/custom/plugins/zsh-syntax-highlighting0
-rw-r--r--.tmux.conf22
m---------.tmux/plugins/tmux-autoreload0
m---------.tmux/plugins/tmux-continuum0
m---------.tmux/plugins/tmux-logging0
m---------.tmux/plugins/tmux-mighty-scroll0
m---------.tmux/plugins/tmux-powerline0
m---------.tmux/plugins/tmux-resurrect0
m---------.tmux/plugins/tmux-sensible0
m---------.tmux/plugins/tpm0
-rw-r--r--.zshrc117
-rw-r--r--Brewfile130
-rw-r--r--README.md36
-rw-r--r--iTerm/DynamicProfiles/wal-profile.json10
-rw-r--r--iTerm/wal-iterm.py191
-rwxr-xr-xscripts/brew.sh9
-rwxr-xr-xscripts/omz.sh23
-rwxr-xr-xscripts/setup-mac.sh64
-rw-r--r--terminal-profiles/Afterglow.terminal222
-rw-r--r--terminal-profiles/Nord.terminal295
49 files changed, 7999 insertions, 0 deletions
diff --git a/.config/nvim/.gitignore b/.config/nvim/.gitignore
new file mode 100644
index 0000000..cc5457a
--- /dev/null
+++ b/.config/nvim/.gitignore
@@ -0,0 +1,8 @@
+tt.*
+.tests
+doc/tags
+debug
+.repro
+foo.*
+*.log
+data
diff --git a/.config/nvim/.neoconf.json b/.config/nvim/.neoconf.json
new file mode 100644
index 0000000..7c48087
--- /dev/null
+++ b/.config/nvim/.neoconf.json
@@ -0,0 +1,15 @@
+{
+ "neodev": {
+ "library": {
+ "enabled": true,
+ "plugins": true
+ }
+ },
+ "neoconf": {
+ "plugins": {
+ "lua_ls": {
+ "enabled": true
+ }
+ }
+ }
+}
diff --git a/.config/nvim/LICENSE b/.config/nvim/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/.config/nvim/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/.config/nvim/README.md b/.config/nvim/README.md
new file mode 100644
index 0000000..185280b
--- /dev/null
+++ b/.config/nvim/README.md
@@ -0,0 +1,4 @@
+# 💤 LazyVim
+
+A starter template for [LazyVim](https://github.com/LazyVim/LazyVim).
+Refer to the [documentation](https://lazyvim.github.io/installation) to get started.
diff --git a/.config/nvim/colors/lushwal.vim b/.config/nvim/colors/lushwal.vim
new file mode 100644
index 0000000..ecf199b
--- /dev/null
+++ b/.config/nvim/colors/lushwal.vim
@@ -0,0 +1,218 @@
+set background=dark
+if exists('g:colors_name')
+hi clear
+if exists('syntax_on')
+syntax reset
+endif
+endif
+let g:colors_name = 'lushwal'
+highlight Normal guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight! link User Normal
+highlight Bold guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=bold
+highlight Boolean guifg=#516757 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Character guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight ColorColumn guifg=#738787 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Comment guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=italic
+highlight Conceal guifg=#576B6B guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight! link Whitespace Conceal
+highlight Conditional guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Constant guifg=#516757 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Cursor guifg=#091515 guibg=#C1C3C3 guisp=NONE blend=NONE gui=NONE
+highlight CursorColumn guifg=#738787 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight CursorLine guifg=NONE guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight CursorLineNr guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight Debug guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Define guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Delimiter guifg=#556261 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight DiagnosticError guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight DiagnosticHint guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight DiagnosticInfo guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight DiagnosticUnderlineError guifg=#546064 guibg=NONE guisp=#546064 blend=NONE gui=underline
+highlight DiagnosticUnderlineHint guifg=#747873 guibg=NONE guisp=#747873 blend=NONE gui=underline
+highlight DiagnosticUnderlineInfo guifg=#5D6365 guibg=NONE guisp=#5D6365 blend=NONE gui=underline
+highlight DiagnosticUnderlineWarn guifg=#4C6F49 guibg=NONE guisp=#4C6F49 blend=NONE gui=underline
+highlight DiagnosticWarn guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight DiffAdd guifg=#5E5F53 guibg=#576B6B guisp=NONE blend=NONE gui=bold
+highlight! link DiffAdded DiffAdd
+highlight DiffChange guifg=#9CA5A5 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight DiffDelete guifg=#546064 guibg=#576B6B guisp=NONE blend=NONE gui=bold
+highlight! link DiffRemoved DiffDelete
+highlight! link diffRemoved DiffDelete
+highlight DiffFile guifg=#546064 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight DiffLine guifg=#5D6365 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight DiffNewFile guifg=#5E5F53 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight DiffText guifg=#5D6365 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight Directory guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight EndOfBuffer guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight Error guifg=#546064 guibg=#C1C3C3 guisp=NONE blend=NONE gui=NONE
+highlight ErrorMsg guifg=#546064 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight Exception guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Float guifg=#516757 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight FoldColumn guifg=#5D6365 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight Folded guifg=#C1C3C3 guibg=#576B6B guisp=NONE blend=NONE gui=italic
+highlight Function guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Identifier guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight IncSearch guifg=#576B6B guibg=#516757 guisp=NONE blend=NONE gui=NONE
+highlight Include guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Italic guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=italic
+highlight Keyword guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Label guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight LineNr guifg=#9CA5A5 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight Macro guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MatchParen guifg=#C1C3C3 guibg=#9CA5A5 guisp=NONE blend=NONE gui=NONE
+highlight MiniCompletionActiveParameter guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MiniCursorword guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=underline
+highlight! link MiniCursorwordCurrent MiniCursorword
+highlight MiniIndentscopePrefix guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=nocombine
+highlight MiniIndentscopeSymbol guifg=#576B6B guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight MiniJump guifg=#5D6365 guibg=NONE guisp=#9CA5A5 blend=NONE gui=underline
+highlight MiniJump2dSpot guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=undercurl
+highlight MiniStarterCurrent guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MiniStarterFooter guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight MiniStarterHeader guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight MiniStarterInactive guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=italic
+highlight MiniStarterItem guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight MiniStarterItemBullet guifg=#556261 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MiniStarterItemPrefix guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MiniStarterQuery guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MiniStarterSection guifg=#556261 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineDevinfo guifg=#C1C3C3 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineFileinfo guifg=#C1C3C3 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineFilename guifg=#4C6F49 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineInactive guifg=#738787 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineModeCommand guifg=#091515 guibg=#747873 guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineModeInsert guifg=#091515 guibg=#5D6365 guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineModeNormal guifg=#091515 guibg=#5E5F53 guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineModeOther guifg=#091515 guibg=#A7A5AC guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineModeReplace guifg=#091515 guibg=#546064 guisp=NONE blend=NONE gui=NONE
+highlight MiniStatuslineModeVisual guifg=#091515 guibg=#516757 guisp=NONE blend=NONE gui=NONE
+highlight MiniSurround guifg=#576B6B guibg=#516757 guisp=NONE blend=NONE gui=NONE
+highlight MiniTablineCurrent guifg=#9CA5A5 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniTablineFill guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MiniTablineHidden guifg=#5E5F53 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniTablineModifiedCurrent guifg=#C1C3C3 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniTablineModifiedHidden guifg=#738787 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniTablineModifiedVisible guifg=#C1C3C3 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniTablineVisible guifg=#9CA5A5 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight MiniTestEmphasis guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight MiniTestFail guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight MiniTestPass guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight MiniTrailspace guifg=#546064 guibg=#C1C3C3 guisp=NONE blend=NONE gui=NONE
+highlight ModeMsg guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight MoreMsg guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight NonText guifg=#9CA5A5 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Number guifg=#516757 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Operator guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight PMenu guifg=#C1C3C3 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight PMenuSel guifg=#C1C3C3 guibg=#5D6365 guisp=NONE blend=NONE gui=NONE
+highlight PmenuSbar guifg=#738787 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight PmenuThumb guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight PreProc guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Question guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Repeat guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Search guifg=#9CA5A5 guibg=#4C6F49 guisp=NONE blend=NONE gui=NONE
+highlight! link MiniTablineTabpagesection Search
+highlight SignColumn guifg=#738787 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight Special guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight SpecialChar guifg=#556261 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight SpecialKey guifg=#9CA5A5 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight SpellBad guifg=#546064 guibg=NONE guisp=#546064 blend=NONE gui=underline
+highlight SpellCap guifg=#4C6F49 guibg=NONE guisp=#4C6F49 blend=NONE gui=underline
+highlight SpellLocal guifg=#747873 guibg=NONE guisp=#747873 blend=NONE gui=underline
+highlight SpellRare guifg=#A7A5AC guibg=NONE guisp=#A7A5AC blend=NONE gui=underline
+highlight Statement guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight StatusLine guifg=#C1C3C3 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight StatusLineNC guifg=#738787 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight StatusLineTerm guifg=#5E5F53 guibg=#5E5F53 guisp=NONE blend=NONE gui=NONE
+highlight StatusLineTermNC guifg=#4C6F49 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight StorageClass guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight String guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Structure guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight TabLine guifg=#9CA5A5 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight TabLineFill guifg=#9CA5A5 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight TabLineSel guifg=#5E5F53 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight Tag guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Title guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight Todo guifg=#4C6F49 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight TooLong guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Type guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Typedef guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight Underlined guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight VertSplit guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight! link WinSeparator VertSplit
+highlight Visual guifg=#091515 guibg=#738787 guisp=NONE blend=NONE gui=NONE
+highlight VisualNOS guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight WarningMsg guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight WildMenu guifg=#C1C3C3 guibg=#5D6365 guisp=NONE blend=NONE gui=NONE
+highlight WinBar guifg=#C1C3C3 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight WinBarNC guifg=#738787 guibg=#091515 guisp=NONE blend=NONE gui=NONE
+highlight gitCommitOverflow guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight gitCommitSummary guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight helpCommand guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight helpExample guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @attribute guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @boolean guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @character guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @character.special guifg=#556261 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @comment guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=italic
+highlight @conditional guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @constant guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @constant.builtin guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @constant.macro guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @constructor guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @debug guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @define guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @exception guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @field guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @float guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @function guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @function.builtin guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @function.macro guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @include guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @keyword guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @keyword.function guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @keyword.operator guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @label guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @method guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @namespace guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @none guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @number guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @operator guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @parameter guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @preproc guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @property guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @punctuation.bracket guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @punctuation.delimiter guifg=#C1C3C3 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @punctuation.special guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight @repeat guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @storageclass guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @string guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @string.escape guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @string.regex guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @string.special guifg=#556261 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @symbol guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @tag guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @tag.attribute guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @tag.delimiter guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.bold guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight @text.danger guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.diff.add guifg=#5E5F53 guibg=#576B6B guisp=NONE blend=NONE gui=bold
+highlight @text.diff.delete guifg=#546064 guibg=#576B6B guisp=NONE blend=NONE gui=bold
+highlight @text.emphasis guifg=#A7A5AC guibg=NONE guisp=NONE blend=NONE gui=italic
+highlight @text.environment guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.environment.name guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.literal guifg=#5E5F53 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.math guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.note guifg=#747873 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.reference guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @text.strike guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=strikethrough
+highlight @text.title guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=bold
+highlight @text.todo guifg=#4C6F49 guibg=#576B6B guisp=NONE blend=NONE gui=NONE
+highlight @text.underline guifg=NONE guibg=NONE guisp=NONE blend=NONE gui=underline
+highlight @text.uri guifg=NONE guibg=#576B6B guisp=NONE blend=NONE gui=underline
+highlight @type guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @type.builtin guifg=#5D6365 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @type.definition guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @variable guifg=#4C6F49 guibg=NONE guisp=NONE blend=NONE gui=NONE
+highlight @variable.builtin guifg=#546064 guibg=NONE guisp=NONE blend=NONE gui=NONE
diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua
new file mode 100644
index 0000000..2514f9e
--- /dev/null
+++ b/.config/nvim/init.lua
@@ -0,0 +1,2 @@
+-- bootstrap lazy.nvim, LazyVim and your plugins
+require("config.lazy")
diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json
new file mode 100644
index 0000000..f557235
--- /dev/null
+++ b/.config/nvim/lazy-lock.json
@@ -0,0 +1,38 @@
+{
+ "LazyVim": { "branch": "main", "commit": "d72127eb936f7f05d88d4fc316bc7e89080d69d8" },
+ "blink.cmp": { "branch": "main", "commit": "327fff91fe6af358e990be7be1ec8b78037d2138" },
+ "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
+ "catppuccin": { "branch": "main", "commit": "8c4125e3c746976ba025dc5d908fa22c6aa09486" },
+ "conform.nvim": { "branch": "master", "commit": "9fd3d5e0b689ec1bf400c53cbbec72c6fdf24081" },
+ "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" },
+ "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" },
+ "gitsigns.nvim": { "branch": "main", "commit": "20ad4419564d6e22b189f6738116b38871082332" },
+ "grug-far.nvim": { "branch": "main", "commit": "3e72397465f774b01aa38e4fe8e6eecf23d766d9" },
+ "lazy.nvim": { "branch": "main", "commit": "db067881fff0fd4be8c00e5bde7492e0e1c77a2f" },
+ "lazydev.nvim": { "branch": "main", "commit": "c2dfe354571a8255c5d3e96a9a4c297c89ce2347" },
+ "lualine.nvim": { "branch": "master", "commit": "3946f0122255bc377d14a59b27b609fb3ab25768" },
+ "lush.nvim": { "branch": "main", "commit": "9c60ec2279d62487d942ce095e49006af28eed6e" },
+ "lushwal.nvim": { "branch": "main", "commit": "2823942833368460c85bb235b4e36789c266e6a2" },
+ "mason-lspconfig.nvim": { "branch": "main", "commit": "3590d66effccc7376d8c3dbe45e8291f9fed2843" },
+ "mason.nvim": { "branch": "main", "commit": "ad7146aa61dcaeb54fa900144d768f040090bff0" },
+ "mini.ai": { "branch": "main", "commit": "11c57180bc9084089206e211ac7aa598bedc9673" },
+ "mini.icons": { "branch": "main", "commit": "284798619aed9f4c1ac1b9417b9a5e3b4b85ef3a" },
+ "mini.pairs": { "branch": "main", "commit": "b9aada8c0e59f2b938e98fbf4eae0799eba96ad9" },
+ "noice.nvim": { "branch": "main", "commit": "5099348591f7d3ba9e547b1e631c694c65bbe0b9" },
+ "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
+ "nvim-lint": { "branch": "master", "commit": "9da1fb942dd0668d5182f9c8dee801b9c190e2bb" },
+ "nvim-lspconfig": { "branch": "master", "commit": "48a9b4dcd9a3611edddd51972d8abb1a289c7724" },
+ "nvim-treesitter": { "branch": "main", "commit": "645f42e85d8665c91a9911c3896afb57d6b8a923" },
+ "nvim-treesitter-textobjects": { "branch": "main", "commit": "1b2d85d3de6114c4bcea89ffb2cd1ce9e3a19931" },
+ "nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" },
+ "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
+ "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
+ "project.nvim": { "branch": "main", "commit": "8c6bad7d22eef1b71144b401c9f74ed01526a4fb" },
+ "shipwright.nvim": { "branch": "master", "commit": "e596ab48328c31873f4f4d2e070243bf9de16ff3" },
+ "snacks.nvim": { "branch": "main", "commit": "14ead48b513207298711224fe70a3abd58fcc190" },
+ "todo-comments.nvim": { "branch": "main", "commit": "411503d3bedeff88484de572f2509c248e499b38" },
+ "tokyonight.nvim": { "branch": "main", "commit": "2642dbb83333e0575d1c3436e1d837926871c5fb" },
+ "trouble.nvim": { "branch": "main", "commit": "d7494d8bc563f8ae8b3f35d78c7478cf842b0ab9" },
+ "ts-comments.nvim": { "branch": "main", "commit": "123a9fb12e7229342f807ec9e6de478b1102b041" },
+ "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
+}
diff --git a/.config/nvim/lazyvim.json b/.config/nvim/lazyvim.json
new file mode 100644
index 0000000..d8bcaf6
--- /dev/null
+++ b/.config/nvim/lazyvim.json
@@ -0,0 +1,10 @@
+{
+ "extras": [
+
+ ],
+ "install_version": 8,
+ "news": {
+ "NEWS.md": "11866"
+ },
+ "version": 8
+} \ No newline at end of file
diff --git a/.config/nvim/lua/config/autocmds.lua b/.config/nvim/lua/config/autocmds.lua
new file mode 100644
index 0000000..4221e75
--- /dev/null
+++ b/.config/nvim/lua/config/autocmds.lua
@@ -0,0 +1,8 @@
+-- Autocmds are automatically loaded on the VeryLazy event
+-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua
+--
+-- Add any additional autocmds here
+-- with `vim.api.nvim_create_autocmd`
+--
+-- Or remove existing autocmds by their group name (which is prefixed with `lazyvim_` for the defaults)
+-- e.g. vim.api.nvim_del_augroup_by_name("lazyvim_wrap_spell")
diff --git a/.config/nvim/lua/config/keymaps.lua b/.config/nvim/lua/config/keymaps.lua
new file mode 100644
index 0000000..2c134f7
--- /dev/null
+++ b/.config/nvim/lua/config/keymaps.lua
@@ -0,0 +1,3 @@
+-- Keymaps are automatically loaded on the VeryLazy event
+-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
+-- Add any additional keymaps here
diff --git a/.config/nvim/lua/config/lazy.lua b/.config/nvim/lua/config/lazy.lua
new file mode 100644
index 0000000..d73bfa1
--- /dev/null
+++ b/.config/nvim/lua/config/lazy.lua
@@ -0,0 +1,53 @@
+local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
+if not (vim.uv or vim.loop).fs_stat(lazypath) then
+ local lazyrepo = "https://github.com/folke/lazy.nvim.git"
+ local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
+ if vim.v.shell_error ~= 0 then
+ vim.api.nvim_echo({
+ { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
+ { out, "WarningMsg" },
+ { "\nPress any key to exit..." },
+ }, true, {})
+ vim.fn.getchar()
+ os.exit(1)
+ end
+end
+vim.opt.rtp:prepend(lazypath)
+
+require("lazy").setup({
+ spec = {
+ -- add LazyVim and import its plugins
+ { "LazyVim/LazyVim", import = "lazyvim.plugins" },
+ -- import/override with your plugins
+ { import = "plugins" },
+ },
+ defaults = {
+ -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup.
+ -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default.
+ lazy = false,
+ -- It's recommended to leave version=false for now, since a lot the plugin that support versioning,
+ -- have outdated releases, which may break your Neovim install.
+ version = false, -- always use the latest git commit
+ -- version = "*", -- try installing the latest stable version for plugins that support semver
+ },
+ install = { colorscheme = { "tokyonight", "habamax" } },
+ checker = {
+ enabled = true, -- check for plugin updates periodically
+ notify = false, -- notify on update
+ }, -- automatically check for plugin updates
+ performance = {
+ rtp = {
+ -- disable some rtp plugins
+ disabled_plugins = {
+ "gzip",
+ -- "matchit",
+ -- "matchparen",
+ -- "netrwPlugin",
+ "tarPlugin",
+ "tohtml",
+ "tutor",
+ "zipPlugin",
+ },
+ },
+ },
+})
diff --git a/.config/nvim/lua/config/options.lua b/.config/nvim/lua/config/options.lua
new file mode 100644
index 0000000..195b7fe
--- /dev/null
+++ b/.config/nvim/lua/config/options.lua
@@ -0,0 +1,6 @@
+-- Options are automatically loaded before lazy.nvim startup
+-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
+-- Add any additional options here
+
+-- Enable transparency support for iTerm2
+vim.opt.termguicolors = true
diff --git a/.config/nvim/lua/plugins/example.lua b/.config/nvim/lua/plugins/example.lua
new file mode 100644
index 0000000..17f53d6
--- /dev/null
+++ b/.config/nvim/lua/plugins/example.lua
@@ -0,0 +1,197 @@
+-- since this is just an example spec, don't actually load anything here and return an empty spec
+-- stylua: ignore
+if true then return {} end
+
+-- every spec file under the "plugins" directory will be loaded automatically by lazy.nvim
+--
+-- In your plugin files, you can:
+-- * add extra plugins
+-- * disable/enabled LazyVim plugins
+-- * override the configuration of LazyVim plugins
+return {
+ -- add gruvbox
+ { "ellisonleao/gruvbox.nvim" },
+
+ -- Configure LazyVim to load gruvbox
+ {
+ "LazyVim/LazyVim",
+ opts = {
+ colorscheme = "gruvbox",
+ },
+ },
+
+ -- change trouble config
+ {
+ "folke/trouble.nvim",
+ -- opts will be merged with the parent spec
+ opts = { use_diagnostic_signs = true },
+ },
+
+ -- disable trouble
+ { "folke/trouble.nvim", enabled = false },
+
+ -- override nvim-cmp and add cmp-emoji
+ {
+ "hrsh7th/nvim-cmp",
+ dependencies = { "hrsh7th/cmp-emoji" },
+ ---@param opts cmp.ConfigSchema
+ opts = function(_, opts)
+ table.insert(opts.sources, { name = "emoji" })
+ end,
+ },
+
+ -- change some telescope options and a keymap to browse plugin files
+ {
+ "nvim-telescope/telescope.nvim",
+ keys = {
+ -- add a keymap to browse plugin files
+ -- stylua: ignore
+ {
+ "<leader>fp",
+ function() require("telescope.builtin").find_files({ cwd = require("lazy.core.config").options.root }) end,
+ desc = "Find Plugin File",
+ },
+ },
+ -- change some options
+ opts = {
+ defaults = {
+ layout_strategy = "horizontal",
+ layout_config = { prompt_position = "top" },
+ sorting_strategy = "ascending",
+ winblend = 0,
+ },
+ },
+ },
+
+ -- add pyright to lspconfig
+ {
+ "neovim/nvim-lspconfig",
+ ---@class PluginLspOpts
+ opts = {
+ ---@type lspconfig.options
+ servers = {
+ -- pyright will be automatically installed with mason and loaded with lspconfig
+ pyright = {},
+ },
+ },
+ },
+
+ -- add tsserver and setup with typescript.nvim instead of lspconfig
+ {
+ "neovim/nvim-lspconfig",
+ dependencies = {
+ "jose-elias-alvarez/typescript.nvim",
+ init = function()
+ require("lazyvim.util").lsp.on_attach(function(_, buffer)
+ -- stylua: ignore
+ vim.keymap.set( "n", "<leader>co", "TypescriptOrganizeImports", { buffer = buffer, desc = "Organize Imports" })
+ vim.keymap.set("n", "<leader>cR", "TypescriptRenameFile", { desc = "Rename File", buffer = buffer })
+ end)
+ end,
+ },
+ ---@class PluginLspOpts
+ opts = {
+ ---@type lspconfig.options
+ servers = {
+ -- tsserver will be automatically installed with mason and loaded with lspconfig
+ tsserver = {},
+ },
+ -- you can do any additional lsp server setup here
+ -- return true if you don't want this server to be setup with lspconfig
+ ---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
+ setup = {
+ -- example to setup with typescript.nvim
+ tsserver = function(_, opts)
+ require("typescript").setup({ server = opts })
+ return true
+ end,
+ -- Specify * to use this function as a fallback for any server
+ -- ["*"] = function(server, opts) end,
+ },
+ },
+ },
+
+ -- for typescript, LazyVim also includes extra specs to properly setup lspconfig,
+ -- treesitter, mason and typescript.nvim. So instead of the above, you can use:
+ { import = "lazyvim.plugins.extras.lang.typescript" },
+
+ -- add more treesitter parsers
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = {
+ ensure_installed = {
+ "bash",
+ "html",
+ "javascript",
+ "json",
+ "lua",
+ "markdown",
+ "markdown_inline",
+ "python",
+ "query",
+ "regex",
+ "tsx",
+ "typescript",
+ "vim",
+ "yaml",
+ },
+ },
+ },
+
+ -- since `vim.tbl_deep_extend`, can only merge tables and not lists, the code above
+ -- would overwrite `ensure_installed` with the new value.
+ -- If you'd rather extend the default config, use the code below instead:
+ {
+ "nvim-treesitter/nvim-treesitter",
+ opts = function(_, opts)
+ -- add tsx and treesitter
+ vim.list_extend(opts.ensure_installed, {
+ "tsx",
+ "typescript",
+ })
+ end,
+ },
+
+ -- the opts function can also be used to change the default opts:
+ {
+ "nvim-lualine/lualine.nvim",
+ event = "VeryLazy",
+ opts = function(_, opts)
+ table.insert(opts.sections.lualine_x, {
+ function()
+ return "😄"
+ end,
+ })
+ end,
+ },
+
+ -- or you can return new options to override all the defaults
+ {
+ "nvim-lualine/lualine.nvim",
+ event = "VeryLazy",
+ opts = function()
+ return {
+ --[[add your custom lualine config here]]
+ }
+ end,
+ },
+
+ -- use mini.starter instead of alpha
+ { import = "lazyvim.plugins.extras.ui.mini-starter" },
+
+ -- add jsonls and schemastore packages, and setup treesitter for json, json5 and jsonc
+ { import = "lazyvim.plugins.extras.lang.json" },
+
+ -- add any tools you want to have installed below
+ {
+ "williamboman/mason.nvim",
+ opts = {
+ ensure_installed = {
+ "stylua",
+ "shellcheck",
+ "shfmt",
+ "flake8",
+ },
+ },
+ },
+}
diff --git a/.config/nvim/lua/plugins/lushwal.lua b/.config/nvim/lua/plugins/lushwal.lua
new file mode 100644
index 0000000..94c5681
--- /dev/null
+++ b/.config/nvim/lua/plugins/lushwal.lua
@@ -0,0 +1,119 @@
+local function apply_transparent_overrides()
+ local hl = vim.api.nvim_set_hl
+ local none = "NONE"
+ hl(0, "Normal", { bg = none })
+ hl(0, "NormalFloat", { bg = none })
+ hl(0, "FloatBorder", { bg = none })
+ hl(0, "EndOfBuffer", { bg = none })
+ hl(0, "CursorLine", { bg = none })
+ hl(0, "LineNr", { bg = none })
+ hl(0, "SignColumn", { bg = none })
+ hl(0, "Pmenu", { bg = none })
+ hl(0, "PmenuSel", { bg = none })
+ hl(0, "TelescopeNormal", { bg = none })
+ hl(0, "TelescopeBorder", { bg = none })
+end
+
+local function set_transparent(on)
+ vim.g.lushwal_transparent = on
+ if on then
+ apply_transparent_overrides()
+ else
+ -- Restore theme defaults (pywal colors with solid background)
+ vim.cmd("colorscheme lushwal")
+ end
+ vim.notify(
+ (on and "Transparency on" or "Transparency off"),
+ vim.log.levels.INFO,
+ { title = "Lushwal" }
+ )
+end
+
+local function toggle_transparent()
+ set_transparent(vim.g.lushwal_transparent ~= true)
+end
+
+return {
+ {
+ "oncomouse/lushwal.nvim",
+ cmd = { "LushwalCompile" },
+ dependencies = {
+ { "rktjmp/lush.nvim" },
+ { "rktjmp/shipwright.nvim" },
+ },
+ lazy = false,
+ init = function()
+ -- Solid background by default (pywal colors). Run :LushwalCompile once after this change to regenerate the theme.
+ vim.g.lushwal_configuration = {
+ transparent_background = false,
+ }
+ end,
+ config = function()
+ vim.g.lushwal_transparent = false -- off by default
+ vim.api.nvim_create_user_command("LushwalToggleTransparency", toggle_transparent, {})
+ vim.keymap.set("n", "<leader>ut", toggle_transparent, { desc = "Toggle transparency" })
+ -- Re-apply transparent overrides after colorscheme load when user had transparency on
+ vim.api.nvim_create_autocmd("ColorScheme", {
+ pattern = "lushwal",
+ callback = function()
+ if vim.g.lushwal_transparent then
+ apply_transparent_overrides()
+ else
+ -- Softer cursor line so the active line doesn't overpower the text
+ vim.api.nvim_set_hl(0, "CursorLine", { bg = "#252530", fg = "NONE" })
+ end
+ end,
+ })
+ -- Apply subtle CursorLine on first load (non-transparent default)
+ vim.defer_fn(function()
+ if vim.g.colors_name == "lushwal" and not vim.g.lushwal_transparent then
+ vim.api.nvim_set_hl(0, "CursorLine", { bg = "#252530", fg = "NONE" })
+ end
+ end, 10)
+ end,
+ },
+ -- Add project.nvim for better project management
+ {
+ "ahmedkhalf/project.nvim",
+ keys = {
+ { "<leader>fp", "<Cmd>Telescope projects<CR>", desc = "Find Projects" },
+ },
+ config = function()
+ require("project_nvim").setup({
+ -- Path where to store the project history for telescope
+ datapath = vim.fn.stdpath("data"),
+ -- Detection methods for projects
+ detection_methods = { "pattern", "lsp" },
+ -- Patterns used to detect projects
+ patterns = {
+ ".git",
+ "_darcs",
+ ".hg",
+ ".bzr",
+ ".svn",
+ "Makefile",
+ "package.json",
+ "Cargo.toml",
+ "requirements.txt",
+ "pyproject.toml",
+ "go.mod",
+ "composer.json",
+ "Gemfile",
+ ".lazy.lua",
+ },
+ -- Only consider these directories as projects
+ scope_chdir = "tab",
+ -- What to do when changing project
+ silent_chdir = false,
+ })
+ require("telescope").load_extension("projects")
+ end,
+ },
+ -- Configure LazyVim to load lushwal
+ {
+ "LazyVim/LazyVim",
+ opts = {
+ colorscheme = "lushwal",
+ },
+ },
+}
diff --git a/.config/nvim/stylua.toml b/.config/nvim/stylua.toml
new file mode 100644
index 0000000..0f90030
--- /dev/null
+++ b/.config/nvim/stylua.toml
@@ -0,0 +1,3 @@
+indent_type = "Spaces"
+indent_width = 2
+column_width = 120
diff --git a/.config/tmux-powerline/config.sh b/.config/tmux-powerline/config.sh
new file mode 100644
index 0000000..14498ef
--- /dev/null
+++ b/.config/tmux-powerline/config.sh
@@ -0,0 +1,469 @@
+# Default configuration file for tmux-powerline.
+# Modeline {
+# vi: foldmarker={,} foldmethod=marker foldlevel=0 tabstop=4 filetype=sh
+# }
+
+# General {
+# Show which segment fails and its exit code.
+export TMUX_POWERLINE_DEBUG_MODE_ENABLED="false"
+# Create error log in tmux runtime temp dir.
+export TMUX_POWERLINE_ERROR_LOGS_ENABLED="false"
+# Only log specific scopes. Space separated list of scopes. Supported scopes: weather.sh lib/text_roll.sh lib/powerline.sh lib/colors.sh config/helpers.sh
+export TMUX_POWERLINE_ERROR_LOGS_SCOPES=""
+# Use patched font symbols.
+export TMUX_POWERLINE_PATCHED_FONT_IN_USE="true"
+
+# The theme to use.
+export TMUX_POWERLINE_THEME="main"
+# Overlay directory to look for themes. There you can put your own themes outside the repo. Fallback will still be the "themes" directory in the repo.
+export TMUX_POWERLINE_DIR_USER_THEMES="${XDG_CONFIG_HOME:-$HOME/.config}/tmux-powerline/themes"
+# Overlay directory to look for segments. There you can put your own segments outside the repo. Fallback will still be the "segments" directory in the repo.
+export TMUX_POWERLINE_DIR_USER_SEGMENTS="${XDG_CONFIG_HOME:-$HOME/.config}/tmux-powerline/segments"
+
+# The initial visibility of the status bar. Can be {"on", "off", "2"}. 2 will create two status lines: one for the window list and one with status bar segments.
+export TMUX_POWERLINE_STATUS_VISIBILITY="on"
+# In case of visibility = 2, where to display window status and where left/right status bars.
+# 0: window status top, left/right status bottom; 1: window status bottom, left/right status top
+export TMUX_POWERLINE_WINDOW_STATUS_LINE=0
+# The status bar refresh interval in seconds.
+# Note that events that force-refresh the status bar (such as window renaming) will ignore this.
+export TMUX_POWERLINE_STATUS_INTERVAL="1"
+# The location of the window list. Can be {"absolute-centre, centre, left, right"}.
+# Note that "absolute-centre" is only supported on `tmux -V` >= 3.2.
+export TMUX_POWERLINE_STATUS_JUSTIFICATION="left"
+
+# The maximum length of the left status bar.
+export TMUX_POWERLINE_STATUS_LEFT_LENGTH="60"
+# The maximum length of the right status bar.
+export TMUX_POWERLINE_STATUS_RIGHT_LENGTH="90"
+
+# The separator to use between windows on the status bar.
+export TMUX_POWERLINE_WINDOW_STATUS_SEPARATOR=""
+
+# Uncomment these if you want to enable tmux bindings for muting (hiding) one of the status bars.
+# E.g. this example binding would mute the left status bar when pressing <prefix> followed by Ctrl-[
+#export TMUX_POWERLINE_MUTE_LEFT_KEYBINDING="C-["
+#export TMUX_POWERLINE_MUTE_RIGHT_KEYBINDING="C-]"
+# }
+
+# air.sh {
+# The data provider to use. Currently only "openweather" is supported.
+export TMUX_POWERLINE_SEG_AIR_DATA_PROVIDER="openweather"
+# How often to update the weather in seconds.
+export TMUX_POWERLINE_SEG_AIR_UPDATE_PERIOD="600"
+# Location of the JSON parser, jq
+export TMUX_POWERLINE_SEG_AIR_JSON="jq"
+# Your location
+# Latitude and Longitude:
+TMUX_POWERLINE_SEG_AIR_LAT=""
+TMUX_POWERLINE_SEG_AIR_LON=""
+# Your Open Weather API Key:
+TMUX_POWERLINE_SEG_AIR_OPEN_WEATHER_API_KEY=""
+# }
+
+# battery.sh {
+# How to display battery remaining. Can be {percentage, cute, hearts}.
+export TMUX_POWERLINE_SEG_BATTERY_TYPE="percentage"
+# How may hearts to show if cute indicators are used.
+export TMUX_POWERLINE_SEG_BATTERY_NUM_HEARTS="5"
+# }
+
+# cpu_temp.sh {
+# CPU temperature icon
+export TMUX_POWERLINE_SEG_CPU_TEMP_ICON=" "
+# Linux only. Regexp to indicate a line containing CPU temperature in 'sensors' output.
+# Check the output of 'sensors' program, decide which line contains desired CPU temperature
+# and store an unique part of that line in this variable. It will be used by 'grep' program
+# to distinct the 'CPU temperature' line from the rest output lines.
+export TMUX_POWERLINE_SEG_CPU_TEMP_SENSORS_LINE_MARKER="Package id 0\|Physical id 0\|temp1"
+# }
+
+# date_week.sh {
+# Symbol for calendar week.
+# export TMUX_POWERLINE_SEG_DATE_WEEK_SYMBOL="󰨳"
+# export TMUX_POWERLINE_SEG_DATE_WEEK_SYMBOL_COLOUR="255"
+# }
+
+# date.sh {
+# date(1) format for the date. If you don't, for some reason, like ISO 8601 format you might want to have "%D" or "%m/%d/%Y".
+export TMUX_POWERLINE_SEG_DATE_FORMAT="%F"
+# }
+
+# disk_usage.sh {
+# Filesystem to retrieve disk space information. Any from the filesystems available (run "df | awk '{print }'" to check them).
+export TMUX_POWERLINE_SEG_DISK_USAGE_FILESYSTEM="/"
+# }
+
+# dropbox_status.sh {
+# The Dropbox glyph to use
+export TMUX_POWERLINE_SEG_DROPBOX_GLYPH="\uf16b"
+# Replace 'Uploading' in the status
+export TMUX_POWERLINE_SEG_DROPBOX_UPLOAD_GLYPH="\uf093"
+# Replace 'Downloading' in the status
+export TMUX_POWERLINE_SEG_DROPBOX_DOWNLOAD_GLYPH="\uf019"
+# Replace 'Indexing' in the status
+export TMUX_POWERLINE_SEG_DROPBOX_INDEX_GLYPH="\uf02e"
+# Replace 'Syncing' in the status
+export TMUX_POWERLINE_SEG_DROPBOX_SYNC_GLYPH="\uf46a"
+# }
+
+# earthquake.sh {
+# The data provider to use. Currently only "goo" is supported.
+export TMUX_POWERLINE_SEG_EARTHQUAKE_DATA_PROVIDER="goo"
+# How often to update the earthquake data in seconds.
+# Note: This is not an early warning detector, use this
+# to be informed about recent earthquake magnitudes in your
+# area. If this is too often, goo may decide to ban you form
+# their server
+export TMUX_POWERLINE_SEG_EARTHQUAKE_UPDATE_PERIOD="600"
+# Only display information when earthquakes are within this many minutes
+export TMUX_POWERLINE_SEG_EARTHQUAKE_ALERT_TIME_WINDOW="60"
+# Display time with this format
+export TMUX_POWERLINE_SEG_EARTHQUAKE_TIME_FORMAT='(%H:%M)'
+# Display only if magnitude is greater or equal to this number
+export TMUX_POWERLINE_SEG_EARTHQUAKE_MIN_MAGNITUDE="3"
+# }
+
+# gcalcli.sh {
+# gcalcli uses 24hr time format by default - if you want to see 12hr time format, set TMUX_POWERLINE_SEG_GCALCLI_MILITARY_TIME_DEFAULT to 0
+export TMUX_POWERLINE_SEG_GCALCLI_24HR_TIME_FORMAT="1"
+# }
+
+# github_notifications.sh {
+# Github token (https://github.com/settings/tokens) with at least "notifications" scope
+export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TOKEN=""
+# Include available notification reasons (https://docs.github.com/en/rest/activity/notifications?apiVersion=2022-11-28#about-notification-reasons),
+# in the format "REASON:SEPARATOR"
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS="approval_requested:-󰴄 |assign:-󰎔 |author:-󰔗 |comment:- |ci_activity:-󰙨 |invitation:- |manual:-󱥃 |mention:- |review_requested:- |security_alert:-󰒃 |state_change:-󱇯 |subscribed:- |team_mention:- "
+# Or if you don't like so many symbols, try the abbreviation variant
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS="approval_requested:areq|assign:as|author:au|comment:co|ci_activity:ci|invitation:in|manual:ma|mention:me|review_requested:rreq|security_alert:sec|state_change:st|subscribed:sub|team_mention:team"
+# Use symbol mode (ignored if you set TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS yourself)
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SYMBOL_MODE="yes"
+# Summarize all notifications
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SUMMARIZE="no"
+# Hide if no notifications
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS="yes"
+# Only show new notifications since date (default: today) (takes up to UPDATE_INTERVAL time to take effect)
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE="$(date +%Y-%m-%dT00:00:00Z)"
+# Enable show only notifications since date (takes up to UPDATE_INTERVAL time to take effect)
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE_ENABLE="no"
+# Maximum notifications to retreive per page (upstream github default per_page, 50)
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_PER_PAGE="50"
+# Maximum pages to retreive
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_MAX_PAGES="10"
+# Update interval to pull latest state from github api
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_UPDATE_INTERVAL="60"
+# Enable Test Mode (to test how the segment will look like when you have notifications for all types/reasons)
+# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TEST_MODE="no"
+# }
+
+# hostname.sh {
+# Use short, long or custom format for the hostname. Can be {"short", "long", "custom"}.
+export TMUX_POWERLINE_SEG_HOSTNAME_FORMAT="short"
+# Custom name to be used when format is "custom"
+export TMUX_POWERLINE_SEG_HOSTNAME_CUSTOM=""
+# }
+
+# ifstat.sh {
+# Symbol for Download.
+# export TMUX_POWERLINE_SEG_IFSTAT_DOWN_SYMBOL="⇊"
+# Symbol for Upload.
+# export TMUX_POWERLINE_SEG_IFSTAT_UP_SYMBOL="⇈"
+# Symbol for Ethernet.
+# export TMUX_POWERLINE_SEG_IFSTAT_ETHERNET_SYMBOL="󰈀"
+# Symbol for WLAN.
+# export TMUX_POWERLINE_SEG_IFSTAT_WLAN_SYMBOL="󱚻"
+# Symbol for WWAN.
+# export TMUX_POWERLINE_SEG_IFSTAT_WWAN_SYMBOL=""
+# Separator for Interfaces.
+# export TMUX_POWERLINE_SEG_IFSTAT_INTERFACE_SEPARATOR=" | "
+# Space separated list of interface names to be excluded. substring match, regexp can be used.
+# Examples:
+# export TMUX_POWERLINE_SEG_IFSTAT_INTERFACE_EXCLUDES="tun" # will exclude 'tun0', 'utun0', 'itun', 'tun08127387'
+# export TMUX_POWERLINE_SEG_IFSTAT_INTERFACE_EXCLUDES="tun0 tuntun" # will exclude 'tun0', 'utun0', 'tuntun'
+# export TMUX_POWERLINE_SEG_IFSTAT_INTERFACE_EXCLUDES="^tun0$ ^tun1$" # excludes exactly 'tun0' and 'tun1'
+# Default:
+# export TMUX_POWERLINE_SEG_IFSTAT_INTERFACE_EXCLUDES="^u?tun[0-9]+$"
+# }
+
+# kubernetes_context.sh {
+# Kubernetes config context display mode {"name_namespace", "name", "namespace"}.
+# export TMUX_POWERLINE_SEG_KUBERNETES_CONTEXT_DISPLAY_MODE="name_namespace"
+# Kubernetes config context symbol.
+# export TMUX_POWERLINE_SEG_KUBERNETES_CONTEXT_SYMBOL="󱃾"
+# Kubernetes config context symbol colour.
+# export TMUX_POWERLINE_SEG_KUBERNETES_CONTEXT_SYMBOL_COLOUR="255"
+# Separator for display mode "name_namespace"
+# TMUX_POWERLINE_SEG_KUBERNETES_CONTEXT_SEPARATOR="󰿟"
+# }
+
+# lan_ip.sh {
+# Symbol for LAN IP.
+# export TMUX_POWERLINE_SEG_LAN_IP_SYMBOL="ⓛ "
+# Symbol colour for LAN IP
+# export TMUX_POWERLINE_SEG_LAN_IP_SYMBOL_COLOUR="255"
+# }
+
+# macos_notification_count.sh {
+
+# }
+
+# mailcount.sh {
+# Mailbox type to use. Can be any of {apple_mail, gmail, maildir, mbox, mailcheck}
+export TMUX_POWERLINE_SEG_MAILCOUNT_MAILBOX_TYPE=""
+
+## Gmail
+# Enter your Gmail username here WITH OUT @gmail.com.( OR @domain)
+export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_USERNAME=""
+# Google password. Recomenned to use application specific password (https://accounts.google.com/b/0/IssuedAuthSubTokens) Leave this empty to get password from OS X keychain.
+# For macOS users : MAKE SURE that you add a key to the keychain in the format as follows
+# Keychain Item name : http://<value-you-fill-in-server-variable-below>
+# Account name : <username-below>@<server-below>
+# Password : Your password ( Once again, try to use 2 step-verification and application-specific password)
+# See http://support.google.com/accounts/bin/answer.py?hl=en&answer=185833 for more info.
+export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_PASSWORD=""
+# Domain name that will complete your email. For normal GMail users it probably is "gmail.com but can be "foo.tld" for Google Apps users.
+export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_SERVER="gmail.com"
+# How often in minutes to check for new mails.
+export TMUX_POWERLINE_SEG_MAILCOUNT_GMAIL_INTERVAL="5"
+
+## Maildir
+# Path to the maildir to check.
+export TMUX_POWERLINE_SEG_MAILCOUNT_MAILDIR_INBOX="$HOME/.mail/inbox/new"
+
+## mbox
+# Path to the mbox to check.
+export TMUX_POWERLINE_SEG_MAILCOUNT_MBOX_INBOX=""
+
+## mailcheck
+# Optional path to mailcheckrc
+export TMUX_POWERLINE_SEG_MAILCOUNT_MAILCHECKRC="$HOME/.mailcheckrc"
+# }
+
+# mode_indicator.sh {
+# Whether the normal & prefix mode section should be enabled. Should be {"true, "false"}.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_NORMAL_AND_PREFIX_MODE_ENABLED="true"
+# Normal mode text & color overrides. Defaults to "normal" & the segment foreground color set in the theme used.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_NORMAL_MODE_TEXT="normal"
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_NORMAL_MODE_TEXT_COLOR=""
+# Prefix mode text & color overrides. Defaults to "prefix" & the segment foreground color set in the theme used.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_PREFIX_MODE_TEXT="prefix"
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_PREFIX_MODE_TEXT_COLOR=""
+# Whether the mouse mode section should be enabled. Should be {"true, "false"}.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_MOUSE_MODE_ENABLED="true"
+# Mouse mode text & color overrides. Defaults to "mouse" & the segment foreground color set in the theme used.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_MOUSE_MODE_TEXT="mouse"
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_MOUSE_MODE_TEXT_COLOR=""
+# Whether the copy mode section should be enabled. Should be {"true, "false"}.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_COPY_MODE_ENABLED="true"
+# Copy mode text & color overrides. Defaults to "copy" & the segment foreground color set in the theme used.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_COPY_MODE_TEXT="copy"
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_COPY_MODE_TEXT_COLOR=""
+# Suspend mode text & color overrides. Defaults to "SUSPEND" & the segment foreground color set in the theme used.
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_SUSPEND_MODE_TEXT="SUSPEND"
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_SUSPEND_MODE_TEXT_COLOR=""
+# Separator text override. Defaults to " • ".
+export TMUX_POWERLINE_SEG_MODE_INDICATOR_SEPARATOR_TEXT=" • "
+# }
+
+# now_playing.sh {
+# Music player to use. Can be any of {audacious, banshee, cmus, apple_music, itunes, lastfm, plexamp, mocp, mpd, mpd_simple, pithos, playerctl, rdio, rhythmbox, spotify, file}.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_MUSIC_PLAYER="lastfm"
+# File to be read in case the song is being read from a file
+export TMUX_POWERLINE_SEG_NOW_PLAYING_FILE_NAME=""
+# Maximum output length.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_MAX_LEN="40"
+# How to handle too long strings. Can be {trim, roll}.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_TRIM_METHOD="trim"
+# Characters per second to roll if rolling trim method is used.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SPEED="2"
+# Mode of roll text {"space", "repeat"}. space: fill up with empty space; repeat: repeat text from beginning
+# export TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_MODE="repeat"
+# Separator for "repeat" roll mode
+# export TMUX_POWERLINE_SEG_NOW_PLAYING_ROLL_SEPARATOR="  "
+# If set to 'true', 'yes', 'on' or '1', played tracks will be logged to a file.
+# export TMUX_POWERLINE_SEG_NOW_PLAYING_TRACK_LOG_ENABLE="false"
+# If enabled, log played tracks to the following file:
+# export TMUX_POWERLINE_SEG_NOW_PLAYING_TRACK_LOG_FILEPATH="$HOME/.now_playing.log"
+# Maximum number of logged song entries. Set to "unlimited" for unlimited entries.
+# export TMUX_POWERLINE_SEG_NOW_PLAYING_TRACK_LOG_MAX_ENTRIES="100"
+
+# Hostname for MPD server in the format "[password@]host"
+export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_HOST="localhost"
+# Port the MPD server is running on.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_PORT="6600"
+# Song display format for mpd_simple. See mpc(1) for delimiters.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_MPD_SIMPLE_FORMAT="%artist% - %title%"
+# Song display format for playerctl. see "Format Strings" in playerctl(1).
+export TMUX_POWERLINE_SEG_NOW_PLAYING_PLAYERCTL_FORMAT="{{ artist }} - {{ title }}"
+# Song display format for rhythmbox. see "FORMATS" in rhythmbox-client(1).
+export TMUX_POWERLINE_SEG_NOW_PLAYING_RHYTHMBOX_FORMAT="%aa - %tt"
+
+# Last.fm
+# Set up steps for Last.fm
+# 1. Make sure jq(1) is installed on the system.
+# 2. Create a new API application at https://www.last.fm/api/account/create (name it tmux-powerline) and copy the API key and insert it below in the setting TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_API_KEY
+# 3. Make sure the API can access your recently played song by going to you user privacy settings https://www.last.fm/settings/privacy and make sure "Hide recent listening information" is UNCHECKED.
+# Username for Last.fm if that music player is used.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_USERNAME=""
+# API Key for the API.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_API_KEY=""
+# How often in seconds to update the data from last.fm.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_LASTFM_UPDATE_PERIOD="30"
+# Fancy char to display before now playing track
+export TMUX_POWERLINE_SEG_NOW_PLAYING_NOTE_CHAR="♫"
+
+# Plexamp
+# Set up steps for Plexamp
+# 1. Make sure jq(1) is installed on the system.
+# 2. Make sure you have an instance of Tautulli that is accessible by the computer running tmux-powerline.
+# Username for Plexamp if that music player is used.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_PLEXAMP_USERNAME=""
+# Hostname for Tautulli server in the format "[password@]host"
+export TMUX_POWERLINE_SEG_NOW_PLAYING_PLEXAMP_TAUTULLI_HOST=""
+# API Key for Tautulli.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_PLEXAMP_TAUTULLI_API_KEY=""
+# How often in seconds to update the data from Plexamp.
+export TMUX_POWERLINE_SEG_NOW_PLAYING_PLEXAMP_UPDATE_PERIOD="30"
+# }
+
+# pwd.sh {
+# Maximum length of output.
+export TMUX_POWERLINE_SEG_PWD_MAX_LEN="40"
+# }
+
+# time.sh {
+# date(1) format for the time. Americans might want to have "%I:%M %p".
+export TMUX_POWERLINE_SEG_TIME_FORMAT="%H:%M"
+# Change this to display a different timezone than the system default.
+# Use TZ Identifier like "America/Los_Angeles"
+# export TMUX_POWERLINE_SEG_TIME_TZ=""
+# }
+
+# tmux_continuum_save.sh {
+# Path to the tmux-continuum git repo.
+export TMUX_POWERLINE_SEG_TMUX_CONTINUUM_PATH="$HOME/.tmux/plugins/tmux-continuum"
+# }
+
+# tmux_continuum_status.sh {
+# Path to the tmux-continuum git repo.
+export TMUX_POWERLINE_SEG_TMUX_CONTINUUM_PATH="$HOME/.tmux/plugins/tmux-continuum"
+# Message to perfix the status indication with.
+export TMUX_POWERLINE_SEG_TMUX_CONTINUUM_PREFIX="Continuum status: "
+# }
+
+# tmux_mem_cpu_load.sh {
+# Arguments passed to tmux-mem-cpu-load.
+# See https://github.com/thewtex/tmux-mem-cpu-load for all available options.
+# export TMUX_POWERLINE_SEG_TMUX_MEM_CPU_LOAD_ARGS="-v"
+# }
+
+# tmux_session_info.sh {
+# Session info format to feed into the command: tmux display-message -p
+# For example, if FORMAT is '[ #S ]', the command is: tmux display-message -p '[ #S ]'
+export TMUX_POWERLINE_SEG_TMUX_SESSION_INFO_FORMAT="#S:#I.#P"
+# }
+
+# utc_time.sh {
+# date(1) format for the UTC time.
+export TMUX_POWERLINE_SEG_UTC_TIME_FORMAT="%H:%M %Z"
+# }
+
+# vcs_branch.sh {
+# Max length of the branch name.
+export TMUX_POWERLINE_SEG_VCS_BRANCH_MAX_LEN=""
+# Symbol when branch length exceeds max length
+# export TMUX_POWERLINE_SEG_VCS_BRANCH_TRUNCATE_SYMBOL="…"
+# Default branch symbol
+export TMUX_POWERLINE_SEG_VCS_BRANCH_DEFAULT_SYMBOL=""
+# Branch symbol for git repositories
+# export TMUX_POWERLINE_SEG_VCS_BRANCH_GIT_SYMBOL="${TMUX_POWERLINE_SEG_VCS_BRANCH_DEFAULT_SYMBOL}"
+# Branch symbol for hg/mercurial repositories
+# export TMUX_POWERLINE_SEG_VCS_BRANCH_HG_SYMBOL="${TMUX_POWERLINE_SEG_VCS_BRANCH_DEFAULT_SYMBOL}"
+# Branch symbol for SVN repositories
+# export TMUX_POWERLINE_SEG_VCS_BRANCH_SVN_SYMBOL="${TMUX_POWERLINE_SEG_VCS_BRANCH_DEFAULT_SYMBOL}"
+# Branch symbol colour for git repositories
+export TMUX_POWERLINE_SEG_VCS_BRANCH_GIT_SYMBOL_COLOUR="5"
+# Branch symbol colour for hg/mercurial repositories
+export TMUX_POWERLINE_SEG_VCS_BRANCH_HG_SYMBOL_COLOUR="45"
+# Branch symbol colour for SVN repositories
+export TMUX_POWERLINE_SEG_VCS_BRANCH_SVN_SYMBOL_COLOUR="220"
+# }
+
+# vcs_compare.sh {
+# Symbol if local branch is behind.
+# export TMUX_POWERLINE_SEG_VCS_COMPARE_AHEAD_SYMBOL="↑ "
+# Symbol colour if local branch is ahead. Defaults to "current segment foreground colour"
+# export TMUX_POWERLINE_SEG_VCS_COMPARE_AHEAD_SYMBOL_COLOUR=""
+# Symbol if local branch is ahead.
+# export TMUX_POWERLINE_SEG_VCS_COMPARE_BEHIND_SYMBOL="↓ "
+# Symbol colour if local branch is behind. Defaults to "current segment foreground colour"
+# export TMUX_POWERLINE_SEG_VCS_COMPARE_BEHIND_SYMBOL_COLOUR=""
+# }
+
+# vcs_modified.sh {
+# Symbol for count of modified vcs files.
+# export TMUX_POWERLINE_SEG_VCS_MODIFIED_SYMBOL="± "
+# }
+
+# vcs_others.sh {
+# Symbol for count of untracked vcs files.
+# export TMUX_POWERLINE_SEG_VCS_OTHERS_SYMBOL="⋯"
+# }
+
+# vcs_rootpath.sh {
+# Display mode for vcs_rootpath.
+# Example: (name: folder name only; path: full path, w/o expansion; user_path: full path, w/ tilde expansion)
+# export TMUX_POWERLINE_SEG_VCS_ROOTPATH_MODE="name"
+# }
+
+# vcs_staged.sh {
+# Symbol for count of staged vcs files.
+# export TMUX_POWERLINE_SEG_VCS_STAGED_SYMBOL="⊕ "
+# }
+
+# vpn.sh {
+# Mode for VPN segment {"both", "ip", "name"}. both: Show NIC/IP; ip: Show only IP; name: Show only NIC name
+# export TMUX_POWERLINE_SEG_VPN_DISPLAY_MODE="both"
+# Space separated list of tunnel interface names. First match is being used. substring match, regexp can be used.
+# Examples:
+# export TMUX_POWERLINE_SEG_VPN_NICS="tun" # will match 'tun0', 'utun0', 'itun', 'tun08127387'
+# export TMUX_POWERLINE_SEG_VPN_NICS="tun0 tuntun" # will match 'tun0', 'utun0', 'tuntun'
+# export TMUX_POWERLINE_SEG_VPN_NICS="^tun0$ ^tun1$" # exactly 'tun0' and 'tun1'
+# Default:
+# export TMUX_POWERLINE_SEG_VPN_NICS='^u?tun[0-9]+$'
+# Symbol to use for vpn tunnel.
+# export TMUX_POWERLINE_SEG_VPN_SYMBOL="󱠾 "
+# Colour for vpn tunnel symbol
+# export TMUX_POWERLINE_SEG_VPN_SYMBOL_COLOUR="255"
+# Symbol for separator
+# export TMUX_POWERLINE_SEG_VPN_DISPLAY_SEPARATOR="󰿟"
+# }
+
+# wan_ip.sh {
+# Symbol for WAN IP
+# export TMUX_POWERLINE_SEG_WAN_IP_SYMBOL="ⓦ "
+# Symbol colour for WAN IP
+# export TMUX_POWERLINE_SEG_WAN_IP_SYMBOL_COLOUR="255"
+# }
+
+# weather.sh {
+# The data provider to use. Currently only "yrno" is supported.
+export TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER="yrno"
+# What unit to use. Can be any of {c,f,k}.
+export TMUX_POWERLINE_SEG_WEATHER_UNIT="c"
+# How often to update the weather in seconds.
+export TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD="600"
+# How often to update the weather location in seconds (this is only used when latitude and longitude settings are set to "auto")
+export TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD="86400"
+# Your location
+# Latitude and Longtitude for use with yr.no
+# Set both to "auto" to detect automatically based on your IP address, or set them manually
+export TMUX_POWERLINE_SEG_WEATHER_LAT="auto"
+export TMUX_POWERLINE_SEG_WEATHER_LON="auto"
+# }
+
+# xkb_layout.sh {
+# Keyboard icon
+export TMUX_POWERLINE_SEG_XKB_LAYOUT_ICON="⌨ "
+# }
diff --git a/.config/tmux-powerline/themes/main.sh b/.config/tmux-powerline/themes/main.sh
new file mode 100644
index 0000000..c558c2b
--- /dev/null
+++ b/.config/tmux-powerline/themes/main.sh
@@ -0,0 +1,230 @@
+# shellcheck shell=bash
+# Pywal Theme - Integrated with pywal colors
+# If changes made here does not take effect, then try to re-create the tmux session to force reload.
+
+# Source pywal colors if available
+if [ -f "${HOME}/.cache/wal/colors.sh" ]; then
+ # shellcheck source=/dev/null
+ source "${HOME}/.cache/wal/colors.sh"
+fi
+
+if tp_patched_font_in_use; then
+ TMUX_POWERLINE_SEPARATOR_LEFT_BOLD=""
+ TMUX_POWERLINE_SEPARATOR_LEFT_THIN=""
+ TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD=""
+ TMUX_POWERLINE_SEPARATOR_RIGHT_THIN=""
+else
+ TMUX_POWERLINE_SEPARATOR_LEFT_BOLD="◀"
+ TMUX_POWERLINE_SEPARATOR_LEFT_THIN="❮"
+ TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD="▶"
+ TMUX_POWERLINE_SEPARATOR_RIGHT_THIN="❯"
+fi
+
+# See Color formatting section below for details on what colors can be used here.
+# Use pywal colors if available, otherwise fallback to defaults
+if [ -n "$background" ] && [ -n "$foreground" ]; then
+ TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR:-"$background"}
+ TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR:-"$foreground"}
+else
+ TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_BACKGROUND_COLOR:-'235'}
+ TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR=${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR:-'255'}
+fi
+# shellcheck disable=SC2034
+TMUX_POWERLINE_SEG_AIR_COLOR=$(tp_air_color)
+
+TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR=${TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR:-$TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD}
+TMUX_POWERLINE_DEFAULT_RIGHTSIDE_SEPARATOR=${TMUX_POWERLINE_DEFAULT_RIGHTSIDE_SEPARATOR:-$TMUX_POWERLINE_SEPARATOR_LEFT_BOLD}
+
+# See `man tmux` for additional formatting options for the status line.
+# The `format regular` and `format inverse` functions are provided as conveniences
+
+# shellcheck disable=SC2128
+if [ -z "$TMUX_POWERLINE_WINDOW_STATUS_CURRENT" ]; then
+ TMUX_POWERLINE_WINDOW_STATUS_CURRENT=(
+ "#[$(tp_format inverse)]"
+ "$TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR"
+ " #I#F "
+ "$TMUX_POWERLINE_SEPARATOR_RIGHT_THIN"
+ " #W "
+ "#[$(tp_format regular)]"
+ "$TMUX_POWERLINE_DEFAULT_LEFTSIDE_SEPARATOR"
+ )
+fi
+
+# shellcheck disable=SC2128
+if [ -z "$TMUX_POWERLINE_WINDOW_STATUS_STYLE" ]; then
+ TMUX_POWERLINE_WINDOW_STATUS_STYLE=(
+ "$(tp_format regular)"
+ )
+fi
+
+# shellcheck disable=SC2128
+if [ -z "$TMUX_POWERLINE_WINDOW_STATUS_FORMAT" ]; then
+ TMUX_POWERLINE_WINDOW_STATUS_FORMAT=(
+ "#[$(tp_format regular)]"
+ " #I#{?window_flags,#F, } "
+ "$TMUX_POWERLINE_SEPARATOR_RIGHT_THIN"
+ " #W "
+ )
+fi
+
+# Format: segment_name [background_color|default_bg_color] [foreground_color|default_fg_color] [non_default_separator|default_separator] [separator_background_color|no_sep_bg_color]
+# [separator_foreground_color|no_sep_fg_color] [spacing_disable|no_spacing_disable] [separator_disable|no_separator_disable]
+#
+# * background_color and foreground_color. Color formatting (see `man tmux` for complete list) or run the color_palette.sh in the tmux-powerline root directory:
+# * Named colors, e.g. black, red, green, yellow, blue, magenta, cyan, white
+# * Hexadecimal RGB string e.g. #ffffff
+# * 'default_fg_color|default_bg_color' for the default theme bg and fg color
+# * 'default' for the default tmux color.
+# * 'terminal' for the terminal's default background/foreground color
+# * The numbers 0-255 for the 256-color palette. Run `tmux-powerline/color-palette.sh` to see the colors.
+# * non_default_separator - specify an alternative character for this segment's separator
+# * 'default_separator' for the theme default separator
+# * separator_background_color - specify a unique background color for the separator
+# * 'no_sep_bg_color' for using the default coloring for the separator
+# * separator_foreground_color - specify a unique foreground color for the separator
+# * 'no_sep_fg_color' for using the default coloring for the separator
+# * spacing_disable - remove space on left, right or both sides of the segment:
+# * "no_spacing_disable" - don't disable spacing (default)
+# * "left_disable" - disable space on the left
+# * "right_disable" - disable space on the right
+# * "both_disable" - disable spaces on both sides
+# * - any other character/string produces no change to default behavior (eg "none", "X", etc.)
+#
+# * separator_disable - disables drawing a separator on this segment, very useful for segments
+# with dynamic background colours (eg tmux_mem_cpu_load):
+# * "no_separator_disable" - don't disable the separator (default)
+# * "separator_disable" - disables the separator
+# * - any other character/string produces no change to default behavior
+#
+# Example segment with separator disabled and right space character disabled:
+# "hostname 33 0 {TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD} 0 0 right_disable separator_disable"
+#
+# Example segment with spacing characters disabled on both sides but not touching the default coloring:
+# "hostname 33 0 {TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD} no_sep_bg_color no_sep_fg_color both_disable"
+#
+# Example segment with changing the foreground color of the default separator:
+# "hostname 33 0 default_separator no_sep_bg_color 120"
+#
+## Note that although redundant the non_default_separator, separator_background_color and
+# separator_foreground_color options must still be specified so that appropriate index
+# of options to support the spacing_disable and separator_disable features can be used
+# The default_* and no_* can be used to keep the default behaviour.
+
+# shellcheck disable=SC1143,SC2128
+if [ -z "$TMUX_POWERLINE_LEFT_STATUS_SEGMENTS" ]; then
+ # Use pywal colors if available, otherwise use defaults
+ # shellcheck disable=SC2154
+ if [ -n "$color5" ] && [ -n "$background" ]; then
+ # shellcheck disable=SC2154
+ TMUX_POWERLINE_LEFT_STATUS_SEGMENTS=(
+ # shellcheck disable=SC2154
+ "tmux_session_info ${color5} ${background}"
+ # shellcheck disable=SC2154
+ "hostname ${color3} ${background}"
+ #"mode_indicator 165 0"
+ #"ifstat 30 255"
+ #"ifstat_sys 30 255"
+ # shellcheck disable=SC2154
+ # "lan_ip ${color6} ${background} ${TMUX_POWERLINE_SEPARATOR_RIGHT_THIN}"
+ #"vpn 24 255 ${TMUX_POWERLINE_SEPARATOR_RIGHT_THIN}"
+ # shellcheck disable=SC2154
+ # "wan_ip ${color6} ${background} ${TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD} ${color2} ${background}"
+ # shellcheck disable=SC2154
+ "vcs_branch ${color2} ${background}"
+ #"vcs_compare 60 255"
+ #"vcs_staged 64 255"
+ #"vcs_modified 9 255"
+ #"vcs_others 245 0"
+ )
+ else
+ TMUX_POWERLINE_LEFT_STATUS_SEGMENTS=(
+ "tmux_session_info 148 234"
+ "hostname 33 0"
+ #"mode_indicator 165 0"
+ #"ifstat 30 255"
+ #"ifstat_sys 30 255"
+ # "lan_ip 24 255 ${TMUX_POWERLINE_SEPARATOR_RIGHT_THIN}"
+ #"vpn 24 255 ${TMUX_POWERLINE_SEPARATOR_RIGHT_THIN}"
+ # "wan_ip 24 255 ${TMUX_POWERLINE_SEPARATOR_RIGHT_BOLD} 29 255"
+ "vcs_branch 29 88"
+ #"vcs_compare 60 255"
+ #"vcs_staged 64 255"
+ #"vcs_modified 9 255"
+ #"vcs_others 245 0"
+ )
+ fi
+fi
+
+# shellcheck disable=SC1143,SC2128
+if [ -z "$TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS" ]; then
+ # Use pywal colors if available, otherwise use defaults
+ # shellcheck disable=SC2154
+ if [ -n "$color1" ] && [ -n "$background" ] && [ -n "$foreground" ]; then
+ # shellcheck disable=SC2154
+ TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS=(
+ #"earthquake 3 0"
+ # shellcheck disable=SC2154
+ "pwd ${color4} ${background}"
+ #"macos_notification_count 29 255"
+ #"mailcount 9 255"
+ "now_playing 234 37"
+ #"cpu 240 136"
+ # shellcheck disable=SC2154
+ # "load ${color8} ${background}"
+ #"tmux_mem_cpu_load 234 136"
+ # shellcheck disable=SC2154
+ "battery ${color5} ${background}"
+ #"air ${TMUX_POWERLINE_SEG_AIR_COLOR} 255"
+ # shellcheck disable=SC2154
+ "weather ${color14} ${background}"
+ #"rainbarf 0 ${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR}"
+ # "$(
+ # if (($(tp_cpu_temp_at_least 60))); then
+ # echo "cpu_temp #ff2020 235"
+ # else
+ # echo "cpu_temp #303080 136"
+ # fi
+ # )" \
+ #"xkb_layout 125 117"
+ #"tmux_continuum_save"
+ #"tmux_continuum_status 14 7"
+ # shellcheck disable=SC2154
+ "date_day ${color1} ${background}"
+ # shellcheck disable=SC2154
+ "date ${color1} ${background} ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}"
+ # shellcheck disable=SC2154
+ "time ${color1} ${background} ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}"
+ #"utc_time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}"
+ )
+ else
+ TMUX_POWERLINE_RIGHT_STATUS_SEGMENTS=(
+ #"earthquake 3 0"
+ "pwd 89 211"
+ #"macos_notification_count 29 255"
+ #"mailcount 9 255"
+ "now_playing 234 37"
+ #"cpu 240 136"
+ # "load 237 167"
+ #"tmux_mem_cpu_load 234 136"
+ "battery 137 127"
+ #"air ${TMUX_POWERLINE_SEG_AIR_COLOR} 255"
+ "weather 37 255"
+ #"rainbarf 0 ${TMUX_POWERLINE_DEFAULT_FOREGROUND_COLOR}"
+ # "$(
+ # if (($(tp_cpu_temp_at_least 60))); then
+ # echo "cpu_temp #ff2020 235"
+ # else
+ # echo "cpu_temp #303080 136"
+ # fi
+ # )" \
+ #"xkb_layout 125 117"
+ #"tmux_continuum_save"
+ #"tmux_continuum_status 14 7"
+ "date_day 235 136"
+ "date 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}"
+ "time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}"
+ #"utc_time 235 136 ${TMUX_POWERLINE_SEPARATOR_LEFT_THIN}"
+ )
+ fi
+fi
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ca9a38
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+firefox/
+.DS_Store
+.lazy.lua
+*.venv* \ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e92d133
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,33 @@
+[submodule ".oh-my-zsh/custom/plugins/zsh-autosuggestions"]
+ path = .oh-my-zsh/custom/plugins/zsh-autosuggestions
+ url = https://github.com/zsh-users/zsh-autosuggestions.git
+[submodule ".oh-my-zsh/custom/plugins/zsh-syntax-highlighting"]
+ path = .oh-my-zsh/custom/plugins/zsh-syntax-highlighting
+ url = https://github.com/zsh-users/zsh-syntax-highlighting.git
+[submodule ".oh-my-zsh/custom/plugins/zsh-autocomplete"]
+ path = .oh-my-zsh/custom/plugins/zsh-autocomplete
+ url = https://github.com/marlonrichert/zsh-autocomplete.git
+[submodule ".tmux/plugins/tmux-autoreload"]
+ path = .tmux/plugins/tmux-autoreload
+ url = https://github.com/b0o/tmux-autoreload.git
+[submodule ".tmux/plugins/tmux-continuum"]
+ path = .tmux/plugins/tmux-continuum
+ url = https://github.com/tmux-plugins/tmux-continuum.git
+[submodule ".tmux/plugins/tmux-logging"]
+ path = .tmux/plugins/tmux-logging
+ url = https://github.com/tmux-plugins/tmux-logging.git
+[submodule ".tmux/plugins/tmux-mighty-scroll"]
+ path = .tmux/plugins/tmux-mighty-scroll
+ url = https://github.com/noscript/tmux-mighty-scroll.git
+[submodule ".tmux/plugins/tmux-powerline"]
+ path = .tmux/plugins/tmux-powerline
+ url = https://github.com/erikw/tmux-powerline.git
+[submodule ".tmux/plugins/tmux-resurrect"]
+ path = .tmux/plugins/tmux-resurrect
+ url = https://github.com/tmux-plugins/tmux-resurrect.git
+[submodule ".tmux/plugins/tmux-sensible"]
+ path = .tmux/plugins/tmux-sensible
+ url = https://github.com/tmux-plugins/tmux-sensible.git
+[submodule ".tmux/plugins/tpm"]
+ path = .tmux/plugins/tpm
+ url = https://github.com/tmux-plugins/tpm.git
diff --git a/.irssi/config b/.irssi/config
new file mode 100644
index 0000000..ac5d6d2
--- /dev/null
+++ b/.irssi/config
@@ -0,0 +1,331 @@
+servers = (
+ { address = "irc.dal.net"; chatnet = "DALnet"; port = "6667"; },
+ {
+ address = "ssl.efnet.org";
+ chatnet = "EFNet";
+ port = "9999";
+ use_tls = "yes";
+ tls_verify = "no";
+ },
+ {
+ address = "irc.esper.net";
+ chatnet = "EsperNet";
+ port = "6697";
+ use_tls = "yes";
+ tls_verify = "yes";
+ },
+ {
+ address = "irc.libera.chat";
+ chatnet = "liberachat";
+ port = "6697";
+ use_tls = "yes";
+ tls_verify = "yes";
+ autoconnect = "yes";
+ },
+ {
+ address = "irc.gamesurge.net";
+ chatnet = "GameSurge";
+ port = "6667";
+ },
+ {
+ address = "ssl.ircnet.ovh";
+ chatnet = "IRCnet";
+ port = "6697";
+ use_tls = "yes";
+ tls_verify = "yes";
+ },
+ { address = "open.ircnet.net"; chatnet = "IRCnet"; port = "6667"; },
+ {
+ address = "irc.ircsource.net";
+ chatnet = "IRCSource";
+ port = "6667";
+ },
+ { address = "irc.netfuze.net"; chatnet = "NetFuze"; port = "6667"; },
+ {
+ address = "irc.oftc.net";
+ chatnet = "OFTC";
+ port = "6697";
+ use_tls = "yes";
+ tls_verify = "yes";
+ },
+ {
+ address = "irc.quakenet.org";
+ chatnet = "QuakeNet";
+ port = "6667";
+ },
+ {
+ address = "irc.rizon.net";
+ chatnet = "Rizon";
+ port = "6697";
+ use_tls = "yes";
+ tls_verify = "yes";
+ },
+ { address = "silc.silcnet.org"; chatnet = "SILC"; port = "706"; },
+ {
+ address = "irc.undernet.org";
+ chatnet = "Undernet";
+ port = "6667";
+ }
+);
+
+chatnets = {
+ DALnet = {
+ type = "IRC";
+ max_kicks = "4";
+ max_msgs = "20";
+ max_whois = "30";
+ };
+ EFNet = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "4";
+ max_whois = "1";
+ };
+ EsperNet = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "4";
+ max_whois = "1";
+ };
+ liberachat = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "4";
+ max_whois = "1";
+ sasl_mechanism = "PLAIN";
+ sasl_username = "";
+ sasl_password = "";
+ };
+ GameSurge = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "1";
+ max_whois = "1";
+ };
+ IRCnet = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "1";
+ max_whois = "1";
+ };
+ IRCSource = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "4";
+ max_whois = "1";
+ };
+ NetFuze = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "1";
+ max_whois = "1";
+ };
+ OFTC = { type = "IRC"; max_kicks = "1"; max_msgs = "1"; max_whois = "1"; };
+ QuakeNet = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "1";
+ max_whois = "1";
+ };
+ Rizon = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "1";
+ max_whois = "1";
+ };
+ SILC = { type = "SILC"; };
+ Undernet = {
+ type = "IRC";
+ max_kicks = "1";
+ max_msgs = "1";
+ max_whois = "1";
+ };
+};
+
+channels = (
+ { name = "#lobby"; chatnet = "EsperNet"; autojoin = "No"; },
+ { name = "#libera"; chatnet = "liberachat"; autojoin = "No"; },
+ { name = "#irssi"; chatnet = "liberachat"; autojoin = "No"; },
+ { name = "#gamesurge"; chatnet = "GameSurge"; autojoin = "No"; },
+ { name = "#irssi"; chatnet = "IRCNet"; autojoin = "No"; },
+ { name = "#ircsource"; chatnet = "IRCSource"; autojoin = "No"; },
+ { name = "#netfuze"; chatnet = "NetFuze"; autojoin = "No"; },
+ { name = "#oftc"; chatnet = "OFTC"; autojoin = "No"; },
+ { name = "silc"; chatnet = "SILC"; autojoin = "No"; }
+);
+
+aliases = {
+ ATAG = "WINDOW SERVER";
+ ADDALLCHANS = "SCRIPT EXEC foreach my \\$channel (Irssi::channels()) { Irssi::command(\"CHANNEL ADD -auto \\$channel->{visible_name} \\$channel->{server}->{tag} \\$channel->{key}\")\\;}";
+ B = "BAN";
+ BACK = "AWAY";
+ BANS = "BAN";
+ BYE = "QUIT";
+ C = "CLEAR";
+ CALC = "EXEC - if command -v bc >/dev/null 2>&1\\; then printf '%s=' '$*'\\; echo '$*' | bc -l\\; else echo bc was not found\\; fi";
+ CHAT = "DCC CHAT";
+ CS = "QUOTE CS";
+ DATE = "TIME";
+ DEHIGHLIGHT = "DEHILIGHT";
+ DESCRIBE = "ACTION";
+ DHL = "DEHILIGHT";
+ EXEMPTLIST = "MODE $C +e";
+ EXIT = "QUIT";
+ GOTO = "SCROLLBACK GOTO";
+ HIGHLIGHT = "HILIGHT";
+ HL = "HILIGHT";
+ HOST = "USERHOST";
+ INVITELIST = "MODE $C +I";
+ J = "JOIN";
+ K = "KICK";
+ KB = "KICKBAN";
+ KN = "KNOCKOUT";
+ LAST = "LASTLOG";
+ LEAVE = "PART";
+ M = "MSG";
+ MS = "QUOTE MS";
+ MUB = "UNBAN *";
+ N = "NAMES";
+ NMSG = "^MSG";
+ NS = "QUOTE NS";
+ OS = "QUOTE OS";
+ P = "PART";
+ Q = "QUERY";
+ RESET = "SET -default";
+ RUN = "SCRIPT LOAD";
+ SAY = "MSG *";
+ SB = "SCROLLBACK";
+ SBAR = "STATUSBAR";
+ SHELP = "QUOTE HELP";
+ SIGNOFF = "QUIT";
+ SV = "MSG * Irssi $J ($V) - https://irssi.org";
+ T = "TOPIC";
+ UB = "UNBAN";
+ UMODE = "MODE $N";
+ UNSET = "SET -clear";
+ W = "WHO";
+ WC = "WINDOW CLOSE";
+ WG = "WINDOW GOTO";
+ WJOIN = "JOIN -window";
+ WI = "WHOIS";
+ WII = "WHOIS $0 $0";
+ WL = "WINDOW LIST";
+ WN = "WINDOW NEW HIDDEN";
+ WQUERY = "QUERY -window";
+ WW = "WHOWAS";
+};
+
+statusbar = {
+
+ items = {
+
+ barstart = "{sbstart}";
+ barend = "{sbend}";
+
+ topicbarstart = "{topicsbstart}";
+ topicbarend = "{topicsbend}";
+
+ time = "{sb $Z}";
+ user = "{sb {sbnickmode $cumode}$N{sbmode $usermode}{sbaway $A}}";
+
+ window = "{sb $winref:$tag/$itemname{sbmode $M}}";
+ window_empty = "{sb $winref{sbservertag $tag}}";
+
+ prompt = "{prompt $[.15]itemname}";
+ prompt_empty = "{prompt $winname}";
+
+ topic = " $topic";
+ topic_empty = " Irssi v$J - https://irssi.org";
+
+ lag = "{sb Lag: $0-}";
+ act = "{sb Act: $0-}";
+ more = "-- more --";
+ };
+
+ default = {
+
+ window = {
+
+ disabled = "no";
+ type = "window";
+ placement = "bottom";
+ position = "1";
+ visible = "active";
+
+ items = {
+ barstart = { priority = "100"; };
+ time = { };
+ user = { };
+ window = { };
+ window_empty = { };
+ lag = { priority = "-1"; };
+ act = { priority = "10"; };
+ more = { priority = "-1"; alignment = "right"; };
+ barend = { priority = "100"; alignment = "right"; };
+ };
+ };
+
+ window_inact = {
+
+ type = "window";
+ placement = "bottom";
+ position = "1";
+ visible = "inactive";
+
+ items = {
+ barstart = { priority = "100"; };
+ window = { };
+ window_empty = { };
+ more = { priority = "-1"; alignment = "right"; };
+ barend = { priority = "100"; alignment = "right"; };
+ };
+ };
+
+ prompt = {
+
+ type = "root";
+ placement = "bottom";
+ position = "100";
+ visible = "always";
+
+ items = {
+ prompt = { priority = "-1"; };
+ prompt_empty = { priority = "-1"; };
+ input = { priority = "10"; };
+ };
+ };
+
+ topic = {
+
+ type = "root";
+ placement = "top";
+ position = "1";
+ visible = "always";
+
+ items = {
+ topicbarstart = { priority = "100"; };
+ topic = { };
+ topic_empty = { };
+ topicbarend = { priority = "100"; alignment = "right"; };
+ };
+ };
+ };
+};
+settings = {
+ core = {
+ real_name = "";
+ user_name = "";
+ nick = "";
+ };
+ "fe-common/core" = { theme = "pipeline"; };
+ "perl/core/scripts" = {
+ awl_shared_sbar = "OFF";
+ neat_maxlength = "16";
+ neat_dynamic = "no";
+ awl_viewer_launch_env = "NOTITLE=1";
+ };
+};
+keyboard = (
+ { key = "meta-[M"; id = "command"; data = "mouse_xterm "; }
+);
+ignores = ( { level = "JOINS PARTS QUITS"; } );
diff --git a/.irssi/default.theme b/.irssi/default.theme
new file mode 100644
index 0000000..79b1af5
--- /dev/null
+++ b/.irssi/default.theme
@@ -0,0 +1,295 @@
+# When testing changes, the easiest way to reload the theme is with /RELOAD.
+# This reloads the configuration file too, so if you did any changes remember
+# to /SAVE it first. Remember also that /SAVE overwrites the theme file with
+# old data so keep backups :)
+
+# TEMPLATES:
+
+# The real text formats that irssi uses are the ones you can find with
+# /FORMAT command. Back in the old days all the colors and texts were mixed
+# up in those formats, and it was really hard to change the colors since you
+# might have had to change them in tens of different places. So, then came
+# this templating system.
+
+# Now the /FORMATs don't have any colors in them, and they also have very
+# little other styling. Most of the stuff you need to change is in this
+# theme file. If you can't change something here, you can always go back
+# to change the /FORMATs directly, they're also saved in these .theme files.
+
+# So .. the templates. They're those {blahblah} parts you see all over the
+# /FORMATs and here. Their usage is simply {name parameter1 parameter2}.
+# When irssi sees this kind of text, it goes to find "name" from abstracts
+# block below and sets "parameter1" into $0 and "parameter2" into $1 (you
+# can have more parameters of course). Templates can have subtemplates.
+# Here's a small example:
+# /FORMAT format hello {colorify {underline world}}
+# abstracts = { colorify = "%G$0-%n"; underline = "%U$0-%U"; }
+# When irssi expands the templates in "format", the final string would be:
+# hello %G%Uworld%U%n
+# ie. underlined bright green "world" text.
+# and why "$0-", why not "$0"? $0 would only mean the first parameter,
+# $0- means all the parameters. With {underline hello world} you'd really
+# want to underline both of the words, not just the hello (and world would
+# actually be removed entirely).
+
+# COLORS:
+
+# You can find definitions for the color format codes in docs/formats.txt.
+
+# There's one difference here though. %n format. Normally it means the
+# default color of the terminal (white mostly), but here it means the
+# "reset color back to the one it was in higher template". For example
+# if there was /FORMAT test %g{foo}bar, and foo = "%Y$0%n", irssi would
+# print yellow "foo" (as set with %Y) but "bar" would be green, which was
+# set at the beginning before the {foo} template. If there wasn't the %g
+# at start, the normal behaviour of %n would occur. If you _really_ want
+# to use the terminal's default color, use %N.
+
+#############################################################################
+
+# default foreground color (%N) - -1 is the "default terminal color"
+default_color = "-1";
+
+# print timestamp/servertag at the end of line, not at beginning
+info_eol = "false";
+
+# these characters are automatically replaced with specified color
+# (dark grey by default)
+replaces = { "[]=" = "%K$*%n"; };
+
+abstracts = {
+ ##
+ ## generic
+ ##
+
+ # text to insert at the beginning of each non-message line
+ line_start = "%B-%n!%B-%n ";
+
+ # timestamp styling, nothing by default
+ timestamp = "$*";
+
+ # any kind of text that needs hilighting, default is to bold
+ hilight = "%_$*%_";
+
+ # any kind of error message, default is bright red
+ error = "%R$*%n";
+
+ # channel name is printed
+ channel = "%_$*%_";
+
+ # nick is printed
+ nick = "%_$*%_";
+
+ # nick host is printed
+ nickhost = "[$*]";
+
+ # server name is printed
+ server = "%_$*%_";
+
+ # some kind of comment is printed
+ comment = "[$*]";
+
+ # reason for something is printed (part, quit, kick, ..)
+ reason = "{comment $*}";
+
+ # mode change is printed ([+o nick])
+ mode = "{comment $*}";
+
+ ##
+ ## channel specific messages
+ ##
+
+ # highlighted nick/host is printed (joins)
+ channick_hilight = "%C$*%n";
+ chanhost_hilight = "{nickhost %c$*%n}";
+
+ # nick/host is printed (parts, quits, etc.)
+ channick = "%c$*%n";
+ chanhost = "{nickhost $*}";
+
+ # highlighted channel name is printed
+ channelhilight = "%c$*%n";
+
+ # ban/ban exception/invite list mask is printed
+ ban = "%c$*%n";
+
+ ##
+ ## messages
+ ##
+
+ # the basic styling of how to print message, $0 = nick mode, $1 = nick
+ msgnick = "%K<%n$0$1-%K>%n %|";
+
+ # message from you is printed. "ownnick" specifies the styling of the
+ # nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the
+ # whole line.
+
+ # Example1: You want the message text to be green:
+ # ownmsgnick = "{msgnick $0 $1-}%g";
+ # Example2.1: You want < and > chars to be yellow:
+ # ownmsgnick = "%Y{msgnick $0 $1-%Y}%n";
+ # (you'll also have to remove <> from replaces list above)
+ # Example2.2: But you still want to keep <> grey for other messages:
+ # pubmsgnick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsgmenick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsghinick = "%K{msgnick $1 $0$2-%n%K}%n";
+ # ownprivmsgnick = "%K{msgnick $*%K}%n";
+ # privmsgnick = "%K{msgnick %R$*%K}%n";
+
+ # $0 = nick mode, $1 = nick
+ ownmsgnick = "{msgnick $0 $1-}";
+ ownnick = "%_$*%n";
+
+ # public message in channel, $0 = nick mode, $1 = nick
+ pubmsgnick = "{msgnick $0 $1-}";
+ pubnick = "%N$*%n";
+
+ # public message in channel meant for me, $0 = nick mode, $1 = nick
+ pubmsgmenick = "{msgnick $0 $1-}";
+ menick = "%Y$*%n";
+
+ # public highlighted message in channel
+ # $0 = highlight color, $1 = nick mode, $2 = nick
+ pubmsghinick = "{msgnick $1 $0$2-%n}";
+
+ # channel name is printed with message
+ msgchannel = "%K:%c$*%n";
+
+ # private message, $0 = nick, $1 = host
+ privmsg = "[%R$0%K(%r$1-%K)%n] ";
+
+ # private message from you, $0 = "msg", $1 = target nick
+ ownprivmsg = "[%r$0%K(%R$1-%K)%n] ";
+
+ # own private message in query
+ ownprivmsgnick = "{msgnick $*}";
+ ownprivnick = "%_$*%n";
+
+ # private message in query
+ privmsgnick = "{msgnick %R$*%n}";
+
+ ##
+ ## Actions (/ME stuff)
+ ##
+
+ # used internally by this theme
+ action_core = "%_ * $*%n";
+
+ # generic one that's used by most actions
+ action = "{action_core $*} ";
+
+ # own action, both private/public
+ ownaction = "{action $*}";
+
+ # own action with target, both private/public
+ ownaction_target = "{action_core $0}%K:%c$1%n ";
+
+ # private action sent by others
+ pvtaction = "%_ (*) $*%n ";
+ pvtaction_query = "{action $*}";
+
+ # public action sent by others
+ pubaction = "{action $*}";
+
+
+ ##
+ ## other IRC events
+ ##
+
+ # whois
+ whois = "%# $[8]0 : $1-";
+
+ # notices
+ ownnotice = "[%r$0%K(%R$1-%K)]%n ";
+ notice = "%K-%M$*%K-%n ";
+ pubnotice_channel = "%K:%m$*";
+ pvtnotice_host = "%K(%m$*%K)";
+ servernotice = "%g!$*%n ";
+
+ # CTCPs
+ ownctcp = "[%r$0%K(%R$1-%K)] ";
+ ctcp = "%g$*%n";
+
+ # wallops
+ wallop = "%_$*%n: ";
+ wallop_nick = "%n$*";
+ wallop_action = "%_ * $*%n ";
+
+ # netsplits
+ netsplit = "%R$*%n";
+ netjoin = "%C$*%n";
+
+ # /names list
+ names_prefix = "";
+ names_nick = "[%_$0%_$1-] ";
+ names_nick_op = "{names_nick $*}";
+ names_nick_halfop = "{names_nick $*}";
+ names_nick_voice = "{names_nick $*}";
+ names_users = "[%g$*%n]";
+ names_channel = "%G$*%n";
+
+ # DCC
+ dcc = "%g$*%n";
+ dccfile = "%_$*%_";
+
+ # DCC chat, own msg/action
+ dccownmsg = "[%r$0%K($1-%K)%n] ";
+ dccownnick = "%R$*%n";
+ dccownquerynick = "%_$*%n";
+ dccownaction = "{action $*}";
+ dccownaction_target = "{action_core $0}%K:%c$1%n ";
+
+ # DCC chat, others
+ dccmsg = "[%G$1-%K(%g$0%K)%n] ";
+ dccquerynick = "%G$*%n";
+ dccaction = "%_ (*dcc*) $*%n %|";
+
+ ##
+ ## statusbar
+ ##
+
+ # default background for all statusbars. You can also give
+ # the default foreground color for statusbar items.
+ sb_background = "%4%w";
+ window_border = "%4%w";
+
+ # default backround for "default" statusbar group
+ #sb_default_bg = "%4";
+ # background for prompt / input line
+ sb_prompt_bg = "%n";
+ # background for info statusbar
+ sb_info_bg = "%8";
+ # background for topicbar (same default)
+ #sb_topic_bg = "%4";
+
+ # text at the beginning of statusbars. "sb" already puts a space there,
+ # so we don't use anything by default.
+ sbstart = "";
+ # text at the end of statusbars. Use space so that it's never
+ # used for anything.
+ sbend = " ";
+
+ topicsbstart = "{sbstart $*}";
+ topicsbend = "{sbend $*}";
+
+ prompt = "[$*] ";
+
+ sb = " %c[%n$*%c]%n";
+ sbmode = "(%c+%n$*)";
+ sbaway = " (%GzZzZ%n)";
+ sbservertag = ":$0 (change with ^X)";
+ sbnickmode = "$0";
+
+ # activity in statusbar
+
+ # ',' separator
+ sb_act_sep = "%c$*";
+ # normal text
+ sb_act_text = "%c$*";
+ # public message
+ sb_act_msg = "%W$*";
+ # hilight
+ sb_act_hilight = "%M$*";
+ # hilight with specified color, $0 = color, $1 = text
+ sb_act_hilight_color = "$0$1-%n";
+};
diff --git a/.irssi/neongold.theme b/.irssi/neongold.theme
new file mode 100644
index 0000000..b624f03
--- /dev/null
+++ b/.irssi/neongold.theme
@@ -0,0 +1,206 @@
+#
+# ███████ █████ ██████ ███████
+# ░░██░░░██ ██░░░██ ██░░░░██░░██░░░██
+# ░██ ░██░███████░██ ░██ ░██ ░██
+# ░██ ░██░██░░░░ ░██ ░██ ░██ ░██
+# ███ ░██░░██████░░██████ ███ ░██
+# ░░░ ░░ ░░░░░░ ░░░░░░ ░░░ ░░
+#
+# ██ ██
+# ░██ ░██
+# █████ ██████ ░██ ░██
+# ██░░░██ ██░░░░██ ░██ ██████
+# ░██ ░██░██ ░██ ░██ ██░░░██
+# ░░██████░██ ░██ ░██░██ ░██
+# ░░░░░██░░██████ ███░░██████
+# █████ ░░░░░░ ░░░ ░░░░░░
+# ░░░░░
+#
+# ▓▓▓▓▓▓▓▓▓▓
+# ░▓ author ▓ xero <x@xero.nu>
+# ░▓ code ▓ http://code.xero.nu/dotfiles
+# ░▓ mirror ▓ http://git.io/.files
+# ░▓▓▓▓▓▓▓▓▓▓
+# ░░░░░░░░░░
+#
+default_color = "-1";
+
+info_eol = "false";
+
+replaces = { "[]" = "%w$*%n"; };
+
+abstracts = {
+
+ indent_default = " + %Y│%n ";
+ line_start = "";
+ timestamp = "";
+ hilight = "%_$*%_";
+ error = "%r$*%n";
+ channel = "%w$*%n";
+ nick = "%_$*%_";
+ nickhost = "%g$*";
+ server = "%_$*%_";
+ comment = "%n(%w$*%n)";
+ reason = "{comment $*}";
+ mode = "{comment $*}";
+
+ channick_hilight = "%g$*%N";
+ chanhost_hilight = "{nickhost $*}";
+
+ channick = "$*";
+ chanhost = "{nickhost $*}";
+
+ channelhilight = "%g$*%n";
+
+ ban = "$*";
+
+ msgnick = "%Y$0%w$1 %Y│ %N";
+ ownmsgnick = "%Y$0%w$1 %Y│ ";
+ ownnick = "%W$*%n";
+ pubnick = "%N$*%n";
+ menick = "%y$*%y";
+
+ # generic one that's used by most actions
+ action = "%b$* %Y│%b";
+
+ # own action, both private/public
+ ownaction = "%b$* %Y│%b";
+
+ # own action with target, both private/public
+ ownaction_target = "{action $*}";
+
+ # private action sent by others
+ pvtaction = "{action $*}";
+ pvtaction_query = "{action $*}";
+
+ # public action sent by others
+ pubaction = "{action $*}";
+
+ whois = "%w │ %n$1-";
+
+ ownnotice = "%NNote n = %Mnew%n $0 ($1-) ";
+ notice = "%M$*%n ";
+ pubnotice_channel = " %N($*)";
+ pvtnotice_host = " %N($*)";
+ servernotice = " %N($*)";
+
+ ownctcp = "%N$0 (%w$1-%N) ";
+ ctcp = "%N$*%n";
+
+ wallop = "%w$*%n: ";
+ wallop_nick = "%n$*";
+ wallop_action = "%w * $*%n ";
+
+ #netsplit = "%w$*%n";
+ #netjoin = "%w$*%n";
+
+ names_users = "%Y┌─┄┄─┄┄──┘ %nusers in %b$1";
+ names_nick = "$2$0%n$1 ";
+ names_nick_op = "{names_nick $* %w}";
+ names_nick_halfop = "{names_nick $* %w}";
+ names_nick_voice = "{names_nick $* %w}";
+ names_prefix = "%Y│ %n$1";
+ names_channel = "%W$*%n";
+
+ dcc = "%g$*%n";
+ dccfile = "%_$*%_";
+
+ dccownmsg = "%g /* $0 ($1-) */";
+ dccownnick = "$*%n";
+ dccownquerynick = "$*%n";
+ dccownaction = "{action $*}";
+ dccownaction_target = "{action $*}";
+
+ dccmsg = "%g/* $1- ($0) */";
+ dccquerynick = "%g$*%n";
+ dccaction = "{action $*}";
+
+ sb_background = "%N%N";
+
+ sb_prompt_bg = "%n";
+
+ sbstart = " %Y┌─┄┄─────┘ %w";
+ sbend = "";
+
+ topicsbstart = "%w$C %Y┄─┄$*";
+ topicsbend = "$*";
+
+ prompt = " %Y└──┄┄%n ";
+
+ sb = "%N$*%N ";
+ #sb = "";
+ sbmode = "%b(%w+%N$*%b)%n";
+ sbaway = "%b(%Naway%b)%N";
+ sbservertag = "%b:%N$0%b(%N^X%b)";
+ #sbservertag = "";
+ sbnickmode = "%w$0%N$1";
+
+ #sb_usercount = "{sb %_$0%_ nicks ($1-)}";
+ #sb_uc_ircops = "%_*%_$*";
+ #sb_uc_ops = "%_@%r$*%n";
+ #sb_uc_halfops = "%_%%%g$*%n";
+ #sb_uc_voices = "%_+%y$*%n";
+ #sb_uc_normal = "%w$*%n";
+ #sb_uc_space = " ";
+
+ #sb_act_sep = "%b$*";
+ #sb_act_text = "%N$*";
+ #sb_act_msg = "%b$*";
+ #sb_act_hilight = "%R%9$*%n";
+ #sb_act_hilight_color = "%R%9$1-%n";
+};
+
+formats = {
+ "fe-common/core" = {
+ #line_start = "{line_start}";
+ line_start_irssi = "{line_start}";
+ join = "%n join %Y┄┄─┤ %n{channick $0} %w(%n{nickhost %w$1}%w)%n joined %w$2";
+ part = "%n part %Y┄┄─┤ %n{channick $0} %w(%n{nickhost %w$1}%w)%n left %w$2 {reason %b$3}";
+ quit = "%n quit %Y┄┄─┤ %nsignoff%w: %n{channick $0}%w {reason %b$2}";
+ kick = "%r kick %Y┄┄─┤ %n{channick $0} was kicked by $2 %w{reason %b$3}";
+ nick_changed = " %Y┄┼┄%w %n{channick $0} %Y>> %W{channick $1}";
+ your_nick_changed = " %Y┄┼┄%w %n{channick $0} %Y>> %W{channick $1}";
+ new_topic = "%Y┌─┄┄─────┘%n\012%Y│ %wtopic %b'$2' %Nset by%b $0\012%Y└─┄┄─┄┄──┐ ";
+ endofnames = "%Y└─┄┄─┄┄──┐ %btotal: {hilight $2} ops, {hilight $3} halfops, {hilight $4} voices, {hilight $5} normals%n";
+ #nick padding
+ pubmsg = "{pubmsgnick $2 {pubnick \00312$[-7]0}}$1";
+ own_msg = "{ownmsgnick $2 {ownnick $[-7]0}}$1";
+ own_msg_channel = "{ownmsgnick $3 {ownnick $[-7]0}{msgchannel $1}}$2";
+ own_msg_private_query = "{ownprivmsgnick {ownprivnick $[-7]2}}$1";
+ pubmsg_me = "{pubmsghinick $[-7]0 {menick $2}}%y$1";
+ pubmsg_me_channel = "{pubmsghinick $3 {menick $[-7]0}{msgchannel $1}}$2";
+ pubmsg_hilight_channel = "{pubmsghinick $0 $[-7]1$4{msgchannel $2}}$3";
+ pubmsg_hilight = "{pubmsghinick $3 {menick $[-7]1}}$2";
+ pubmsg_channel = "{pubmsgnick {pubnick %G$[-7]0}$2}$1";
+ msg_private_query = "{privmsgnick $[-7]0}$2";
+ };
+ "fe-common/irc" = {
+ chanmode_change = "%n mode %Y┄┄─┤ %w(%B{channick $1}%w) %nby %B$2";
+ server_chanmode_change = "%n mode %Y┄┄─┤ %w{channick $1} %n(%w$2%n)";
+ whois = "%Y┌─┄┄ %n\012%Y│ %wuser %b$0 %w(%n$1%b@%n$2%w) %n\012%Y│ %wname %n$3%n";
+ whois_idle = "%Y│ %widle%b %|$1d $2h $3m $4s";
+ whois_idle_signon = "%Y│ %widle%b %|$1d $2h $3m $4s {comment signon: $5}";
+ whois_server = "%Y│ %wserv%b %|$1 {comment $2}";
+ whois_oper = "%Y│ %woper%b {hilight $1}";
+ whois_registered = "%Y│ %wrgis%n yes";
+ whois_help = "%Y│ %whelp%b available for help";
+ whois_modes = "%Y│ %wmode%b $1";
+ whois_realhost = "%Y│ %wreal%b $1-";
+ whois_usermode = "%Y│ %wumod%b $1";
+ whois_channels = "%Y│ %wchan%b %|$1";
+ whois_away = "%Y│ %waway%b %|$1";
+ whois_special = "%Y│ %winfo%b {comment %|$1}";
+ whois_extra = "%Y│ %wextr%b %|$1";
+ end_of_whois = "%Y└─┄┄ ";
+ whois_not_found = "%Y──┄┄ %wthere is no such nick %b$0";
+ topic = "%ntopic %Y┄┄─┤ %B$0 %b$1";
+ topic_info = " %Y┄┄─┤ %wset by %b$0 %B(%w$1%B)";
+ channel_synced = "%n sync %Y┄┄─┤ %nin {hilight $1} secs";
+ channel_created = "%n %Y┄┄─┤ %ncreated $1";
+ action_core = "%b$[-8]0 %Y│ %b$1";
+ own_action = "{ownaction $[-8]0} $1";
+ action_private = "{pvtaction $[-8]0}$1";
+ action_private_query = "{pvtaction_query $[-8} $2";
+ action_public = "{pubaction $[-8]0}$1";
+ };
+};
diff --git a/.irssi/pipeline.theme b/.irssi/pipeline.theme
new file mode 100644
index 0000000..15b5bff
--- /dev/null
+++ b/.irssi/pipeline.theme
@@ -0,0 +1,270 @@
+#!/bin/bash
+#
+# pipeline
+#
+# An Irssi theme inspired by madcow and skeita
+#
+# Copyright (c) 2016 Beau Hastings. All rights reserved.
+# License: GNU General Public License v2
+#
+# Author: Beau Hastings <beausy@gmail.com>
+# URL: https://github.com/hastinbe/irssi-theme-pipeline
+
+replaces = { "/[]=" = "%K$*%n"; "*@+." = "%B$*%n"; };
+
+#replaces = { "!@+" = "%r$*%n"; };
+info_eol = "false";
+
+abstracts = {
+ ##
+ ## generic
+ ##
+
+ # text to insert at the beginning of each non-message line
+ #line_start = "%b.%c.%C.%n ";
+ line_start = "";
+
+ # timestamp styling, nothing by default
+ timestamp = "%B$*%n";
+ #timestamp = "%y$*%n";
+
+ # any kind of text that needs hilighting, default is to bold
+ hilight = "%_$*%_";
+
+ # any kind of error message, default is bright red
+ error = "%R$*%n";
+
+ # channel name is printed
+ #channel = "$*";
+ channel = "%_$*%_";
+
+ # nick is printed
+ nick = "$*";
+
+ # nick host is printed
+ nickhost = "$*";
+
+ # server name is printed
+ server = "%_$*%_";
+
+ # some kind of comment is printed
+ #comment = "$*";
+ comment = "%b[%n$*%b]%n";
+
+ # reason for something is printed (part, quit, kick, ..)
+ reason = "{comment %_$*%_}";
+
+ # mode change is printed ([+o nick])
+ #mode = "{comment %n[%W$*]%n}";
+ mode = "%b$*%n";
+
+ ##
+ ## channel specific messages
+ ##
+
+ # highlighted nick/host is printed (joins)
+ channick_hilight = "$*";
+ chanhost_hilight = "{nickhost $*}";
+
+ # nick/host is printed (parts, quits, etc.)
+ channick = "%W$*%n";
+ chanhost = "{nickhost $*}";
+
+ # highlighted channel name is printed
+ channelhilight = "%R$*%n";
+
+ # ban/ban exception/invite list mask is printed
+ ban = "%r$*%n";
+
+ ##
+ ## messages
+ ##
+
+ # the basic styling of how to print message, $0 = nick mode, $1 = nick
+ #msgnick = "<%C$0%n$1-%n> %|";
+ msgnick = "%b%n$0$1%K |%n %|";
+
+ # message from you is printed. "msgownnick" specifies the styling of the
+ # nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the
+ # whole line.
+
+ # Example1: You want the message text to be green:
+ # ownmsgnick = "{msgnick $0 $1-}%g";
+ # Example2.1: You want < and > chars to be yellow:
+ # ownmsgnick = "%Y{msgnick $0 $1-%Y}%n";
+ # (you'll also have to remove <> from replaces list above)
+ # Example2.2: But you still want to keep <> grey for other messages:
+ # pubmsgnick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsgmenick = "%K{msgnick $0 $1-%K}%n";
+ # pubmsghinick = "%K{msgnick $1 $0$2-%n%K}%n";
+ # ownprivmsgnick = "%K{msgnick $*%K}%n";
+ # privmsgnick = "%K{msgnick %R$*%K}%n";
+
+ # $0 = nick mode, $1 = nick
+ ownmsgnick = "{msgnick $0 $1-}%W";
+ ownnick = "%y$*%n";
+
+ # public message in channel, $0 = nick mode, $1 = nick
+ pubmsgnick = "{msgnick %b$0%n %w$1%n}";
+ #pubmsgnick = "{msgnick $0$1-}";
+ pubnick = "%w$*%n";
+
+ # public message in channel meant for me, $0 = nick mode, $1 = nick
+ #pubmsgmenick = "%Y{msgnick %B$0%n %w$1%n}%w";
+ pubmsgmenick = "{msgnick $0$1-}";
+ menick = "%g$*%n";
+
+ # public highlighted message in channel
+ # $0 = highlight color, $1 = nick mode, $2 = nick
+ #pubmsghinick = "%Y{msgnick %B$1 %w$2}%w";
+ pubmsghinick = "{msgnick $1 $0$2-%n}";
+
+ # channel name is printed with message
+ msgchannel = "%b:$*%n";
+
+ # private message, $0 = nick, $1 = host
+ #privmsg = "%b.%c.%C.%n(%c$0%n[%c$1]) ";
+ privmsg = "[%w$0!%b$1-%n] ";
+
+ # private message from you, $0 = "msg", $1 = target nick
+ #ownprivmsg = "%b.%c.%C.%n[%cmsg%n(%c$1%n)] ";
+ ownprivmsg = "{msgnick $*}";
+
+ # own private message in query
+ ownprivmsgnick = "{msgnick %W$*%w}";
+ ownprivnick = "%W$0%n%w";
+
+ # private message in query
+ privmsgnick = "{msgnick %B$*%w}";
+
+ ##
+ ## Actions (/ME stuff)
+ ##
+
+ # used internally by this theme
+ action_core = "%W*%w $*%n";
+
+ # generic one that's used by most actions
+ action = "%w{action_core %w$*} ";
+
+ # own action, both private/public
+ ownaction = "{action $*}";
+
+ # own action with target, both private/public
+ ownaction_target = "{action_core $0}%K:%b$1%n ";
+
+ # private action sent by others
+ pvtaction = "%w $*%n ";
+ pvtaction_query = "{action $*}";
+
+ # public action sent by others
+ pubaction = "{action $*}";
+
+
+ ##
+ ## other IRC events
+ ##
+
+ # notices
+ ownnotice = "%b>%c>%C> %c$0%B!%c$1%n: ";
+ notice = "%b$*%n ";
+ pubnotice_channel = "%K:%m$*";
+ pubnotice_host = "%K(%m$*%K)";
+ servernotice = "%g!$*%n ";
+
+ # CTCPs
+ ownctcp = "%b>%c>%C> %c$0%B!%c$1%n: ";
+ ctcp = "%m$*%n";
+
+ # wallops
+ wallop = "%W$*%n: ";
+ wallop_nick = "%n$*";
+ wallop_action = "%W * $*%n ";
+
+ # netsplits
+ netsplit = "%B$*%n";
+ netjoin = "%B$*%n";
+
+ # /names list
+ names_nick = "[%_$0%_%w$1-%n] ";
+ names_users = "%b$*%n:";
+ names_channel = "%B$*%n";
+
+ # DCC
+ dcc = "%b$*%n";
+ dccfile = "%_$*%_";
+
+ # DCC chat, own msg/action
+ dccownmsg = "[%b$0%K($1-%K)%n] ";
+ dccownnick = "%B$*%n";
+ dccownaction = "{action $*}";
+ dccownaction_target = "{action_core $0}%K:%b$1%n ";
+
+ # DCC chat, others
+ dccmsg = "[%B$1-%K(%b$0%K)%n] ";
+ dccquerynick = "%B$*%n";
+ dccaction = "%W (*dcc*) $*%n %|";
+
+ ##
+ ## statusbar
+ ##
+
+ # background of statusbar
+ sb_background = "%0";
+
+ prompt = "%w$*%n%B:%W ";
+
+ # default statusbar item style
+ sb = "%B[%W$*%B]%n";
+ sbmode = " %b+%n$*";
+ sbaway = " (%Baway%n)";
+ sbservertag = ":%W$0";
+ sbmore = "%_-- more --%_";
+ sblag = "{sb L: %B$*}";
+ sbmail = "{sb M: $*}";
+
+ # activity. Det is used for hilights when display doesn't support colors
+ sbact = "{sb {sbact_act $0}{sbact_det $1}}";
+ sbact_act = "A: $*";
+ sbact_det = " D: $*";
+
+ # usercount
+ sb_usercount = "{sb %W$0%n $1-}";
+ sb_uc_ircops = "%_*%_%K/%R$*%n";
+ sb_uc_ops = "%_@%_%K/%G$*%n";
+ sb_uc_halfops = "%_=%_%K/%g$*%n";
+ sb_uc_voices = "%_+%_%K/%Y$*%n";
+ sb_uc_normal = "%_.%_%K/%W$*%n";
+ sb_uc_space = " ";
+
+};
+
+# %r%n%_$0%_$1%K |%n %|
+formats = {
+ "fe-common/core" = {
+ pubmsg = "{pubmsgnick $2 {pubnick $[-16]0}}$1";
+ join = " %_%Bjoin%_%K |%n %g{channick_hilight $0}%K!%n{chanhost_hilight $1}";
+ part = " %_%Bpart%_%K |%n %W{channick $0}%K!%n{chanhost $1}: {reason $3}";
+ kick = " %_%Bkick%_%K |%n %r{channick $0} %nby {nick $2} from {channel $1}: {reason $3}";
+ quit = " %_%Bquit%_%K |%n %W{channick $0}%K!%n{chanhost $1}: {reason $2}";
+ nick_changed = " %_%Bnick%_%K |%n {nick %w$0%n} %Nis now {nick %W$1%n}";
+ endofnames = "{channel $0}: {hilight $1} nicks ({comment @/{hilight $2} +/{hilight $3} -/{hilight $4}})";
+ own_msg = "{ownmsgnick $2 {ownnick $[-16]0}}$1";
+ own_msg_channel = "{ownmsgnick $3 {ownnick $[-16]0}{msgchannel $1}}$2";
+ pubmsg_me = "{pubmsgmenick $2 {menick $[-16]0}}$1";
+ pubmsg_me_channel = "{pubmsgmenick $3 {menick $[-16]0}{msgchannel $1}}$2";
+ pubmsg_hilight = "{pubmsghinick $0 $3 $[-16]1}$2";
+ pubmsg_channel = "{pubmsgnick $3 {pubnick $[-16]0}{msgchannel $1}}$2";
+ chanmode_change = " %_%Bmode%_%K |%n {$channel $0} %W{channick_hilight $2} %nsets mode %B{$mode $1}";
+ channel_mode = " %_%Bmode%_%K |%n {$channel $0} %W{channick_hilight $2} %nsets mode %B{$mode $1}";
+ };
+ "fe-common/text" = { window_info_sticky = "%# Sticky : $0"; };
+ "fe-common/irc" = {
+ chanmode_change = " %_%Bmode%_%K |%n %y{channick_hilight $2} %nsets mode %b{$mode $1} %non {$channelhilight $0}";
+ whois = "{hilight $0} [{nickhost $1@$2}] [$whois_country]%: ircname : $3";
+ server_chanmode_change = "{netsplit ServerMode}/{channelhilight $0}: {mode $1} by {nick $2}";
+ whois_server = " server : $1 ({comment $2})";
+ own_action = "{ownaction $0}%|$1";
+ action_public = "{pubaction $0}%|$1";
+ };
+};
diff --git a/.irssi/scripts/adv_windowlist.pl b/.irssi/scripts/adv_windowlist.pl
new file mode 100644
index 0000000..839814e
--- /dev/null
+++ b/.irssi/scripts/adv_windowlist.pl
@@ -0,0 +1,2988 @@
+use strict;
+use warnings;
+
+our $VERSION = '1.11'; # 28b8dcf69e0355e
+our %IRSSI = (
+ authors => 'Nei',
+ contact => 'Nei @ anti@conference.jabber.teamidiot.de',
+ url => "http://anti.teamidiot.de/",
+ name => 'adv_windowlist',
+ description => 'Adds a permanent advanced window list on the right or in a status bar.',
+ sbitems => 'awl_shared',
+ license => 'GNU GPLv2 or later',
+ );
+
+# UPGRADE NOTE
+# ============
+# for users of 0.7 or earlier series, please note that appearance
+# settings have moved to /format, i.e. inside your theme!
+# the fifo (screen) has been replaced by an external viewer script
+
+# Usage
+# =====
+# copy the script to ~/.irssi/scripts/
+#
+# In irssi:
+#
+# /run adv_windowlist
+#
+# In your shell (for example a tmux split):
+#
+# perl ~/.irssi/scripts/adv_windowlist.pl
+#
+# To use sbar mode instead:
+#
+# /toggle awl_viewer
+#
+# Hint: to get rid of the old [Act:] display
+# /statusbar window remove act
+#
+# to get it back:
+# /statusbar window add -after lag -priority 10 act
+
+# Options
+# =======
+# formats can be cleared with /format -delete
+#
+# /format awl_display_(no)key(_active|_visible) <string>
+# * string : Format String for one window. The following $'s are expanded:
+# $C : Name
+# $N : Number of the Window
+# $Q : meta-Keymap
+# $H : Start hilighting
+# $S : Stop hilighting
+# /+++++++++++++++++++++++++++++++++,
+# | **** I M P O R T A N T : **** |
+# | |
+# | don't forget to use $S if you |
+# | used $H before! |
+# | |
+# '+++++++++++++++++++++++++++++++++/
+# key : a key binding that goes to this window could be detected in /bind
+# nokey : no such key binding was detected
+# active : window would receive the input you are currently typing
+# visible : window is also visible on screen but not active (a split window)
+#
+# /format awl_name_display <string>
+# * string : Format String for window names
+# $0 : name as formatted by the settings
+#
+# /format awl_display_header <string>
+# * string : Format String for this header line. The following $'s are expanded:
+# $C : network tag
+#
+# /format awl_separator(2) <string>
+# * string : Character to use between the channel entries
+# variant 2 can be used for alternating separators (only in status bar
+# without block display)
+#
+# /format awl_abbrev_chars <string>
+# * string : Character to use when shortening long names. The second character
+# will be used if two blocks need to be filled.
+#
+# /format awl_title <string>
+# * string : Text to display in the title string or title bar
+#
+# /format awl_viewer_item_bg <string>
+# * string : Format String specifying the viewer's item background colour
+#
+# /set awl_prefer_name <ON|OFF>
+# * this setting decides whether awl will use the active_name (OFF) or the
+# window name as the name/caption in awl_display_*.
+# That way you can rename windows using /window name myownname.
+#
+# /set awl_hide_empty <num>
+# * if visible windows without items should be hidden from the window list
+# set it to 0 to show all windows
+# 1 to hide visible windows without items (negative exempt
+# active window)
+#
+# /set awl_custom_key_re <regex>
+# * regex : which symbolic key names to show in $Q (for example F-keys)
+#
+# /set awl_detach <list>
+# * list of windows that should be hidden from the window list. you
+# can also use /awl detach and /awl attach to manage this
+# setting. an optional data_level can be specified with ",num"
+#
+# /set awl_detach_data <num>
+# * num : hide the detached window if its data_level is below num
+#
+# /set awl_detach_aht <ON|OFF>
+# * if enabled, also detach all windows listed in the
+# activity_hide_targets setting
+#
+# /set awl_hide_data <num>
+# * num : hide the window if its data_level is below num
+# set it to 0 to basically disable this feature,
+# 1 if you don't want windows without activity to be shown
+# 2 to show only those windows with channel text or hilight
+# 3 to show only windows with hilight (negative exempt active window)
+#
+# /set awl_hide_name_data <num>
+# * num : hide the name of the window if its data_level is below num
+# (only works in status bar without block display)
+# you will want to change your formats to add $H...$S around $Q or $N
+# if you plan to use this
+#
+# /set awl_maxlines <num>
+# * num : number of lines to use for the window list (0 to disable, negative
+# lock)
+#
+# /set awl_maxcolumns <num>
+# * num : number of columns to use for the window list when using the
+# tmux integration (0 to disable)
+#
+# /set awl_block <num>
+# * num : width of a column in viewer mode (negative values = block
+# display in status bar mode)
+# /+++++++++++++++++++++++++++++++++,
+# | ****** W A R N I N G ! ****** |
+# | |
+# | If your block display looks |
+# | DISTORTED, you need to add the |
+# | following line to your .theme |
+# | file under |
+# | abstracts = { : |
+# | |
+# | sb_act_none = "%K$*"; |
+# | |
+# '+++++++++++++++++++++++++++++++++/
+#
+# /set awl_sbar_maxlength <ON|OFF>
+# * if you enable the maxlength setting, the block width will be used as a
+# maximum length for the non-block status bar mode too.
+#
+# /set awl_height_adjust <num>
+# * num : how many lines to leave empty in viewer mode
+#
+# /set awl_sort <-data_level|-last_line|refnum>
+# * you can change the window sort order with this variable
+# -data_level : sort windows with hilight first
+# -last_line : sort windows in order of activity
+# refnum : sort windows by window number
+# active/server/tag : sort by server name
+# lru : sort windows with the last recently used last
+# "-" reverses the sort order
+# typechecks are supported via ::, e.g. active::Query or active::Irc::Query
+# undefinedness can be checked with ~, e.g. ~active
+# string comparison can be done with =, e.g. name=(status)
+# to make sort case insensitive, use #i, e.g. name#i
+# any key in the window hash can be tested, e.g. active/chat_type=XMPP
+# multiple criteria can be separated with , or +, e.g. -data_level+-last_line
+#
+# /set awl_placement <top|bottom>
+# /set awl_position <num>
+# * these settings correspond to /statusbar because awl will create
+# status bars for you
+# (see /help statusbar to learn more)
+#
+# /set awl_all_disable <ON|OFF>
+# * if you set awl_all_disable to ON, awl will also remove the
+# last status bar it created if it is empty.
+# As you might guess, this only makes sense with awl_hide_data > 0 ;)
+#
+# /set awl_viewer <ON|OFF>
+# * enable the external viewer script
+#
+# /set awl_viewer_launch <ON|OFF>
+# * try to auto-launch the viewer under tmux or with a shell command
+# /awl restart is required all auto-launch related settings to take
+# effect
+#
+# /set awl_viewer_tmux_position <left|top|right|bottom|custom>
+# * try to split in this direction when using tmux for the viewer
+# custom : use custom_command setting
+#
+# /set awl_viewer_xwin_command <shell command>
+# * custom command to run in order to start the viewer when irssi is
+# running under X
+# %A - gets replaced by the command to run the viewer
+# %qA - additionally quote the command
+#
+# /set awl_viewer_custom_command <shell command>
+# * custom command to run in order to start the viewer
+#
+# /set awl_viewer_launch_env <string>
+# * specific environment settings for use on viewer auto-launch,
+# without the AWL_ prefix
+#
+# /set awl_shared_sbar <left<right|OFF>
+# * share a status bar for the first awl item, you will need to manually
+# /statusbar window add -after lag -priority 10 awl_shared
+# left : space in cells occupied on the left of status bar
+# right : space occupied on the right
+# Note: you need to replace "left" AND "right" with the appropriate numbers!
+#
+# /set awl_path <path>
+# * path to the file which the viewer script reads
+#
+# /set fancy_abbrev <no|head|strict|fancy>
+# * how to shorten too long names
+# no : shorten in the middle
+# head : always cut off the ends
+# strict : shorten repeating substrings
+# fancy : combination of no+strict
+#
+# /set awl_custom_xform <perl code>
+# * specify a custom routine to transform window names
+# example: s/^#// remove the #-mark of IRC channels
+# the special flags $CHANNEL / $TAG / $QUERY / $NAME can be
+# tested in conditionals
+#
+# /set awl_last_line_shade <timeout>
+# * set timeout to shade activity base colours, to enable
+# you also need to add +-last_line to awl_sort
+# (requires 256 colour support)
+#
+# /set awl_no_mode_hint <ON|OFF>
+# * whether to show the hint of running the viewer script in the
+# status bar
+#
+# /set awl_mouse <ON|OFF>
+# * enable the terminal mouse in irssi
+# (use the awl-patched mouse.pl for gestures and commands if you need
+# them and disable mouse_escape)
+#
+# /set awl_mouse_offset <num>
+# * specifies where on the screen is the awl status bar
+# (0 = on top/bottom, 1 = one additional line in between,
+# e.g. prompt)
+# you MUST set this correctly otherwise the mouse coordinates will
+# be off
+#
+# /set mouse_scroll <num>
+# * how many lines the mouse wheel scrolls
+#
+# /set mouse_escape <num>
+# * seconds to disable the mouse, when not clicked on the windowlist
+#
+
+# Commands
+# ========
+# /awl detach <num>
+# * hide the current window from the window list. num specifies the
+# data_level (optional)
+#
+# /awl attach
+# * unhide the current window from the window list
+#
+# /awl ack
+# * change to the next window with activity, ignoring detached windows
+#
+# /awl redraw
+# * redraws the windowlist. There may be occasions where the
+# windowlist can get destroyed so you can use this command to
+# force a redraw.
+#
+# /awl restart
+# * restart the connection to the viewer script.
+
+# Viewer script
+# =============
+# When run from the command line, adv_windowlist acts as the viewer
+# script to be used together with the irssi script to display the
+# window list in a sidebar/terminal of its own.
+#
+# One optional parameter is accepted, the awl_path
+#
+# The viewer can be configured by three environment variables:
+#
+# AWL_HI9=1
+# * interpret %9 as high-intensity toggle instead of bold. This had
+# been the default prior to version 0.9b8
+#
+# AWL_AUTOFOCUS=0
+# * disable auto-focus behaviour when activating a window
+#
+# AWL_NOTITLE=1
+# * disable the title bar
+
+# Nei =^.^= ( anti@conference.jabber.teamidiot.de )
+
+no warnings 'redefine';
+use constant IN_IRSSI => __PACKAGE__ ne 'main' || $ENV{IRSSI_MOCK};
+use constant SCRIPT_FILE => __FILE__;
+no if !IN_IRSSI, strict => (qw(subs refs));
+use if IN_IRSSI, Irssi => ();
+use if IN_IRSSI, 'Irssi::TextUI' => ();
+use v5.10;
+use Encode;
+use Storable ();
+use IO::Socket::UNIX;
+use List::Util qw(min max reduce);
+use Hash::Util qw(lock_keys);
+use Text::ParseWords qw(shellwords);
+
+BEGIN {
+ if ($] < 5.012) {
+ *CORE::GLOBAL::length = *CORE::GLOBAL::length = sub (_) {
+ defined $_[0] ? CORE::length($_[0]) : undef
+ };
+ }
+ *Irssi::active_win = {}; # hide incorrect warning
+}
+
+unless (IN_IRSSI) {
+ local *_ = \@ARGV;
+ &AwlViewer::main;
+ exit;
+}
+
+
+use constant GLOB_QUEUE_TIMER => 100;
+
+our $BLOCK_ALL; # localized blocker
+my @actString; # status bar texts
+my @win_items;
+my $currentLines = 0;
+my %awins;
+my $globTime; # timer to limit remake calls
+
+my %CHANGED;
+my $VIEWER_MODE;
+my $MOUSE_ON;
+my %mouse_coords;
+my %statusbars;
+my %S; # settings
+my $settings_str = '1';
+my $window_sort_func;
+my $custom_xform;
+my $custom_key_re = qr/(?!)/;
+my ($sb_base_width, $sb_base_width_pre, $sb_base_width_post);
+my $print_text_activity;
+my $shade_line_timer;
+my ($screenHeight, $screenWidth);
+my %viewer;
+
+my (%keymap, %nummap, %wnmap, %specialmap, %wnmap_exp, %custom_key_map);
+my %banned_channels;
+my %detach_map;
+my %abbrev_cache;
+
+use constant setc => 'awl';
+
+sub set ($) {
+ setc . '_' . $_[0]
+}
+
+sub add_statusbar {
+ for (@_) {
+ # add subs
+ my $l = set $_;
+ {
+ my $close = $_;
+ no strict 'refs';
+ *{$l} = sub { awl($close, @_) };
+ }
+ Irssi::command("^statusbar $l reset");
+ Irssi::command("statusbar $l enable");
+ if (lc $S{placement} eq 'top') {
+ Irssi::command("statusbar $l placement top");
+ }
+ if (my $x = $S{position}) {
+ Irssi::command("statusbar $l position $x");
+ }
+ Irssi::command("statusbar $l add -priority 100 -alignment left barstart");
+ Irssi::command("statusbar $l add $l");
+ Irssi::command("statusbar $l add -priority 100 -alignment right barend");
+ Irssi::command("statusbar $l disable");
+ Irssi::statusbar_item_register($l, '$0', $l);
+ $statusbars{$_} = 1;
+ Irssi::command("statusbar $l enable");
+ }
+}
+
+sub remove_statusbar {
+ for (@_) {
+ my $l = set $_;
+ Irssi::command("statusbar $l disable");
+ Irssi::command("statusbar $l reset");
+ Irssi::statusbar_item_unregister($l);
+ {
+ no strict 'refs';
+ undef &{$l};
+ }
+ delete $statusbars{$_};
+ }
+}
+
+my $awl_shared_empty = sub {
+ return if $BLOCK_ALL;
+ my ($item, $get_size_only) = @_;
+ $item->default_handler($get_size_only, '', '', 0);
+};
+
+sub syncLines {
+ my $maxLines = $S{maxlines};
+ my $newLines = ($maxLines > 0 and @actString > $maxLines) ?
+ $maxLines :
+ ($maxLines < 0) ?
+ -$maxLines :
+ @actString;
+ $currentLines = 1 if !$currentLines && $S{shared_sbar};
+ if ($S{shared_sbar} && !$statusbars{shared}) {
+ my $l = set 'shared';
+ {
+ no strict 'refs';
+ *{$l} = sub {
+ return if $BLOCK_ALL;
+ my ($item, $get_size_only) = @_;
+
+ my $text = $actString[0];
+ my $title = _get_format(set 'title');
+ if (length $title) {
+ $title =~ s{\\(.)|(.)}{
+ defined $2 ? quotemeta $2
+ : $1 eq 'V' ? '\u'
+ : $1 eq ':' ? quotemeta ':%n'
+ : $1 =~ /^[uUFQE]$/ ? "\\$1"
+ : quotemeta "\\$1"
+ }sge;
+ $title = eval qq{"$title"};
+ $title .= ' ';
+ }
+ my $pat = defined $text ? "{sb $title\$*}" : '{sb }';
+ $text //= '';
+ $item->default_handler($get_size_only, $pat, $text, 0);
+ };
+ }
+ $statusbars{shared} = 1;
+ remove_statusbar (0) if $statusbars{0};
+ }
+ elsif ($statusbars{shared} && !$S{shared_sbar}) {
+ add_statusbar (0) if $currentLines && $newLines;
+ delete $statusbars{shared};
+ my $l = set 'shared';
+ {
+ no strict 'refs';
+ *{$l} = $awl_shared_empty;
+ }
+ }
+ if ($currentLines == $newLines) { return; }
+ elsif ($newLines > $currentLines) {
+ add_statusbar ($currentLines .. ($newLines - 1));
+ }
+ else {
+ remove_statusbar (reverse ($newLines .. ($currentLines - 1)));
+ }
+ $currentLines = $newLines;
+}
+
+sub awl {
+ return if $BLOCK_ALL;
+ my ($line, $item, $get_size_only) = @_;
+
+ my $text = $actString[$line];
+ my $pat = defined $text ? '{sb $*}' : '{sb }';
+ $text //= '';
+ $item->default_handler($get_size_only, $pat, $text, 0);
+}
+
+# remove old statusbars
+{ my %killBar;
+ sub get_old_status {
+ my ($textDest, $cont, $cont_stripped) = @_;
+ if ($textDest->{level} == MSGLEVEL_CLIENTCRAP and $textDest->{target} eq '' and !defined $textDest->{server}) {
+ my $name = quotemeta(set '');
+ if ($cont_stripped =~ m/^$name(\d+)\s/) { $killBar{$1} = 1; }
+ Irssi::signal_stop;
+ }
+ }
+ sub killOldStatus {
+ %killBar = ();
+ Irssi::signal_add_first('print text' => 'get_old_status');
+ Irssi::command('statusbar');
+ Irssi::signal_remove('print text' => 'get_old_status');
+ remove_statusbar(keys %killBar);
+ }
+}
+
+sub _add_map {
+ my ($type, $target, $map) = @_;
+ ($type->{$target}) = sort { length $a <=> length $b || $a cmp $b }
+ $map, exists $type->{$target} ? $type->{$target} : ();
+}
+
+sub get_keymap {
+ my ($textDest, undef, $cont_stripped) = @_;
+ if ($textDest->{level} == MSGLEVEL_CLIENTCRAP and $textDest->{target} eq '' and !defined $textDest->{server}) {
+ my $one_meta_or_ctrl_key = qr/((?:meta-)*?)(?:(meta-|\^)(\S)|(\w+))/;
+ $cont_stripped = as_uni($cont_stripped);
+ if ($cont_stripped =~ m/((?:$one_meta_or_ctrl_key-)*$one_meta_or_ctrl_key)\s+(.*)$/) {
+ my ($combo, $command) = ($1, $10);
+ my $map = '';
+ while ($combo =~ s/(?:-|^)$one_meta_or_ctrl_key$//) {
+ my ($level, $ctl, $key, $nkey) = ($1, $2, $3, $4);
+ my $numlevel = ($level =~ y/-//);
+ if (not defined $key and $nkey =~ /^($custom_key_re)$/) {
+ $key = $nkey;
+ }
+ $ctl = '' if !$ctl || $ctl ne '^';
+ $map = ('-' x ($numlevel%2)) . ('+' x ($numlevel/2)) .
+ $ctl . (defined $key ? $key : "\01$nkey\01") . $map;
+ }
+ for ($command) {
+ last unless length $map;
+ if (/^change_window (\d+)/i) {
+ _add_map(\%nummap, $1, $map);
+ }
+ elsif (/^(?:command window goto|change_window) (\S+)/i) {
+ my $window = $1;
+ if ($window !~ /\D/) {
+ _add_map(\%nummap, $window, $map);
+ }
+ elsif (lc $window eq 'active') {
+ _add_map(\%specialmap, '_active', $map);
+ }
+ else {
+ _add_map(\%wnmap, $window, $map);
+ }
+ }
+ elsif (/^(?:active_window|command ((awl )?ack))/i) {
+ _add_map(\%specialmap, '_active', $map);
+ $viewer{use_ack} = $1;
+ }
+ elsif (/^command window last/i) {
+ _add_map(\%specialmap, '_last', $map);
+ }
+ elsif (/^(?:upper_window|command window up)/i) {
+ _add_map(\%specialmap, '_up', $map);
+ }
+ elsif (/^(?:lower_window|command window down)/i) {
+ _add_map(\%specialmap, '_down', $map);
+ }
+ elsif (/^key\s+(\w+)/i) {
+ $custom_key_map{$1} = $map;
+ }
+ }
+ }
+ Irssi::signal_stop;
+ }
+}
+
+sub update_keymap {
+ %nummap = %wnmap = %specialmap = %custom_key_map = ();
+ Irssi::signal_remove('command bind' => 'watch_keymap');
+ Irssi::signal_add_first('print text' => 'get_keymap');
+ Irssi::command('bind');
+ Irssi::signal_remove('print text' => 'get_keymap');
+ for (keys %custom_key_map) {
+ if (exists $custom_key_map{$_} &&
+ $custom_key_map{$_} =~ s/\01(\w+)\01/exists $custom_key_map{$1} ? $custom_key_map{$1} : "\02"/ge) {
+ if ($custom_key_map{$_} =~ /\02/) {
+ delete $custom_key_map{$_};
+ }
+ else {
+ redo;
+ }
+ }
+ }
+ for my $keymap (\(%specialmap, %wnmap, %nummap)) {
+ for (keys %$keymap) {
+ if ($keymap->{$_} =~ s/\01(\w+)\01/exists $custom_key_map{$1} ? $custom_key_map{$1} : "\02"/ge) {
+ if ($keymap->{$_} =~ /\02/) {
+ delete $keymap->{$_};
+ }
+ }
+ }
+ }
+ Irssi::signal_add('command bind' => 'watch_keymap');
+ delete $viewer{client_keymap};
+ &wl_changed;
+}
+
+# watch keymap changes
+sub watch_keymap {
+ Irssi::timeout_add_once(1000, 'update_keymap', undef);
+}
+
+{ my %strip_table = (
+ # fe-common::core::formats.c:format_expand_styles
+ # delete format_backs format_fores bold_fores other stuff
+ (map { $_ => '' } (split //, '04261537' . 'kbgcrmyw' . 'KBGCRMYW' . 'U9_8I:|FnN>#[' . 'pP')),
+ # escape
+ (map { $_ => $_ } (split //, '{}%')),
+ );
+ sub ir_strip_codes { # strip %codes
+ my $o = shift;
+ $o =~ s/(%(%|Z.{6}|z.{6}|X..|x..|.))/exists $strip_table{$2} ? $strip_table{$2} :
+ $2 =~ m{x(?:0[a-f]|[1-6][0-9a-z]|7[a-x])|z[0-9a-f]{6}}i ? '' : $1/gex;
+ $o
+ }
+}
+## ir_parse_special -- wrapper around parse_special
+## $i - input format
+## $args - array ref of arguments to format
+## $win - different target window (default current window)
+## $flags - different kind of escape flags (default 4|8)
+## returns formatted str
+sub ir_parse_special {
+ my $o;
+ my $i = shift;
+ my $args = shift // [];
+ y/ /\177/ for @$args; # hack to escape spaces
+ my $win = shift || Irssi::active_win;
+ my $flags = shift // 0x4|0x8;
+ my @cmd_args = ($i, (join ' ', @$args), $flags);
+ my $server = Irssi::active_server();
+ if (ref $win and ref $win->{active}) {
+ $o = $win->{active}->parse_special(@cmd_args);
+ }
+ elsif (ref $win and ref $win->{active_server}) {
+ $o = $win->{active_server}->parse_special(@cmd_args);
+ }
+ elsif (ref $server) {
+ $o = $server->parse_special(@cmd_args);
+ }
+ else {
+ $o = &Irssi::parse_special(@cmd_args);
+ }
+ $o =~ y/\177/ /;
+ $o
+}
+
+sub sb_format_expand { # Irssi::current_theme->format_expand wrapper
+ Irssi::current_theme->format_expand(
+ $_[0],
+ (
+ Irssi::EXPAND_FLAG_IGNORE_REPLACES
+ |
+ ($_[1] ? 0 : Irssi::EXPAND_FLAG_IGNORE_EMPTY)
+ )
+ )
+}
+
+{ my $term_type = Irssi::version > 20040819 ? 'term_charset' : 'term_type';
+ if (Irssi->can('string_width')) {
+ *screen_length = sub { Irssi::string_width($_[0]) };
+ }
+ else {
+ local $@;
+ eval { require Text::CharWidth; };
+ unless ($@) {
+ *screen_length = sub { Text::CharWidth::mbswidth($_[0]) };
+ }
+ else {
+ my $err = $@; chomp $err; $err =~ s/\sat .* line \d+\.$//;
+ #Irssi::print("%_$IRSSI{name}: warning:%_ Text::CharWidth module failed to load. Length calculation may be off! Error was:");
+ print "%_$IRSSI{name}:%_ $err";
+ *screen_length = sub {
+ my $temp = shift;
+ if (lc Irssi::settings_get_str($term_type) eq 'utf-8') {
+ Encode::_utf8_on($temp);
+ }
+ length($temp)
+ };
+ }
+ }
+ sub as_uni {
+ no warnings 'utf8';
+ Encode::decode(Irssi::settings_get_str($term_type), $_[0], 0)
+ }
+ sub as_tc {
+ Encode::encode(Irssi::settings_get_str($term_type), $_[0], 0)
+ }
+}
+
+sub sb_length {
+ screen_length(ir_strip_codes($_[0]))
+}
+
+sub run_custom_xform {
+ local $@;
+ eval {
+ $custom_xform->()
+ };
+ if ($@) {
+ $@ =~ /^(.*)/;
+ print '%_'.(set 'custom_xform').'%_ died (disabling): '.$1;
+ $custom_xform = undef;
+ }
+}
+
+sub remove_uniform {
+ my $o = shift;
+ $o =~ s/^xmpp:(.*?[%@]).+\.[^.]+$/$1/ or
+ $o =~ s#^psyc://.+\.[^.]+/([@~].*)$#$1#;
+ if ($custom_xform) {
+ run_custom_xform() for $o;
+ }
+ $o
+}
+
+sub remove_uniform_vars {
+ my $win = shift;
+ my $name = __PACKAGE__ . '::custom_xform::' . $win->{active}{type}
+ if ref $win->{active} && $win->{active}{type};
+ no strict 'refs';
+ local ${$name} = 1 if $name;
+ remove_uniform(+shift);
+}
+
+sub lc1459 {
+ my $x = shift;
+ $x =~ y/][\\^/}{|~/;
+ lc $x
+}
+
+sub window_list {
+ my $i = 0;
+ map { $_->[1] } sort $window_sort_func map { [ $i++, $_ ] } Irssi::windows;
+}
+
+sub _calculate_abbrev {
+ my ($wins, $abbrevList) = @_;
+ if ($S{fancy_abbrev} !~ /^(no|off|head)/i) {
+ my @nameList = map { ref $_ ? remove_uniform_vars($_, as_uni($_->get_active_name) // '') : '' } @$wins;
+ for (my $i = 0; $i < @nameList - 1; ++$i) {
+ my ($x, $y) = ($nameList[$i], $nameList[$i + 1]);
+ s/^[+#!=]// for $x, $y;
+ my $res = exists $abbrev_cache{$x}{$y} ? $abbrev_cache{$x}{$y}
+ : $abbrev_cache{$x}{$y} = string_LCSS($x, $y);
+ if (defined $res) {
+ for ($nameList[$i], $nameList[$i + 1]) {
+ $abbrevList->{$_} //= int((index $_, $res) + (length $res) / 2);
+ }
+ }
+ }
+ }
+}
+
+my %act_last_line_shades = (
+ r => [qw[ 50 40 30 20 ]],
+ g => [qw[ 1O 1I 1C 16 ]],
+ y => [qw[ 5O 4I 3C 26 ]],
+ b => [qw[ 15 14 13 12 ]],
+ m => [qw[ 54 43 32 21 ]],
+ c => [qw[ 1S 1L 1E 17 ]],
+ w => [qw[ 7W 7T 7Q 3E ]],
+ K => [qw[ 7M 7K 27 7H ]],
+ R => [qw[ 60 50 40 30 ]],
+ G => [qw[ 1U 1O 1I 1C ]],
+ Y => [qw[ 6U 5O 4I 3C ]],
+ B => [qw[ 2B 2A 29 28 ]],
+ M => [qw[ 65 54 43 32 ]],
+ C => [qw[ 1Z 1S 1L 1E ]],
+ W => [qw[ 6Z 5S 7R 7O ]],
+ );
+
+sub _format_display {
+ my (undef, $format, $cformat, $hilight, $name, $number, $key, $win) = @_;
+ if ($print_text_activity && $S{line_shade}) {
+ my @hilight_code = split /\177/, sb_format_expand("{$hilight \177}"), 2;
+ my $max_time = max(1, log($S{line_shade}) - log(1000));
+ my $time_delta = min(3, min($max_time, log(max(1, time - $win->{last_line}))) / $max_time * 3);
+ if ($hilight_code[0] =~ /%(.)/ && exists $act_last_line_shades{$1}) {
+ $hilight = 'sb_act_hilight_color %X'.$act_last_line_shades{$1}[$time_delta];
+ }
+ }
+ $cformat = '$0' unless length $cformat;
+ my %map = ('$C' => $cformat, '$N' => '$1', '$Q' => '$2');
+ $format =~ s<(\$.)><$map{$1}//$1>ge;
+ $format =~ s<\$H((?:\$.|[^\$])*?)\$S><{$hilight $1%n}>g;
+ my @ret = ir_parse_special(sb_format_expand($format), [$name, $number, $key], $win);
+ @ret
+}
+
+sub _get_format {
+ Irssi::current_theme->get_format(__PACKAGE__, @_)
+}
+
+sub _is_detached {
+ my ($win, $active_number) = @_;
+ my $level = $win->{data_level} // 0;
+ my $number = $win->{refnum};
+ my $name = lc1459( as_uni($win->{name}) );
+ my $active = lc1459( as_uni($win->get_active_name) // '' );
+ my $tag = $win->{active} && $win->{active}{server} ? lc1459( as_uni($win->{active}{server}{tag}) // '' ) : '';
+ my @cond = ($number);
+ push @cond, "$name" if length $name;
+ push @cond, "$tag/$active" if length $tag && length $active;
+ push @cond, "$active" if length $active;
+ push @cond, "$tag/*", "$tag/::all" if length $tag;
+ push @cond, "*", "::all";
+ for my $cond (@cond) {
+ if (exists $detach_map{ $cond }) {
+ my $dd = $detach_map{ $cond } // $S{detach_data};
+ return $win->{data_level} < abs $dd
+ && ($number != $active_number || 0 <= $dd);
+ }
+ }
+ return;
+}
+
+sub _calculate_items {
+ my ($wins, $abbrevList) = @_;
+
+ my $display_header = _get_format(set 'display_header');
+ my $name_format = _get_format(set 'name_display');
+ my $abbrev_chars = as_uni(_get_format(set 'abbrev_chars'));
+
+ my %displays;
+
+ my $active = Irssi::active_win;
+ @win_items = ();
+ %keymap = (%nummap, %wnmap_exp);
+
+ my ($numPad, $keyPad) = (0, 0);
+ if ($VIEWER_MODE or $S{block} < 0) {
+ $numPad = length((sort { length $b <=> length $a } keys %keymap)[0]) // 0;
+ $keyPad = length((sort { length $b <=> length $a } values %keymap)[0]) // 0;
+ }
+ my $last_net;
+ my ($abbrev1, $abbrev2) = $abbrev_chars =~ /(\X)(.*)/;
+ my @abbrev_chars = ('~', "\x{301c}");
+ unless (defined $abbrev1 && screen_length(as_tc($abbrev1)) == 1) { $abbrev1 = $abbrev_chars[0] }
+ unless (length $abbrev2) {
+ $abbrev2 = $abbrev1;
+ if ($abbrev1 eq $abbrev_chars[0]) {
+ $abbrev2 = $abbrev_chars[1];
+ }
+ else {
+ $abbrev2 = $abbrev1;
+ }
+ }
+ if (screen_length(as_tc($abbrev2)) == 1) {
+ $abbrev2 x= 2;
+ }
+ while (screen_length(as_tc($abbrev2)) > 2) {
+ chop $abbrev2;
+ }
+ unless (screen_length(as_tc($abbrev2)) == 2) {
+ $abbrev2 = $abbrev_chars[1];
+ }
+ for my $win (@$wins) {
+ my $global_tag_header_mode;
+
+ next unless ref $win;
+
+ my $backup_win = Storable::dclone($win);
+ delete $backup_win->{active} unless ref $backup_win->{active};
+
+ $global_tag_header_mode =
+ $display_header && ($last_net // '') ne ($backup_win->{active}{server}{tag} // '');
+
+ if ($win->{data_level} < abs $S{hide_data}
+ && ($win->{refnum} != $active->{refnum} || 0 <= $S{hide_data})) {
+ next; }
+ elsif (exists $awins{$win->{refnum}} && $S{hide_empty} && !$win->items
+ && ($win->{refnum} != $active->{refnum} || 0 <= $S{hide_empty})) {
+ next; }
+ elsif (_is_detached($win, $active->{refnum})) {
+ next; }
+
+ my $colour = $win->{hilight_color} // '';
+ my $hilight = do {
+ if ($win->{data_level} == 0) { 'sb_act_none'; }
+ elsif ($win->{data_level} == 1) { 'sb_act_text'; }
+ elsif ($win->{data_level} == 2) { 'sb_act_msg'; }
+ elsif ($colour ne '') { "sb_act_hilight_color $colour"; }
+ elsif ($win->{data_level} == 3) { 'sb_act_hilight'; }
+ else { 'sb_act_special'; }
+ };
+ my $number = $win->{refnum};
+
+ my ($name, $display, $cdisplay);
+ if ($global_tag_header_mode) {
+ $display = $display_header;
+ $name = as_uni($backup_win->{active}{server}{tag}) // '';
+ if ($custom_xform) {
+ no strict 'refs';
+ local ${ __PACKAGE__ . '::custom_xform::TAG' } = 1;
+ run_custom_xform() for $name;
+ }
+ }
+ else {
+ my @display = ('display_nokey');
+ if (defined $keymap{$number} and $keymap{$number} ne '') {
+ unshift @display, map { (my $cpy = $_) =~ s/_no/_/; $cpy } @display;
+ }
+ if (exists $awins{$number}) {
+ unshift @display, map { my $cpy = $_; $cpy .= '_visible'; $cpy } @display;
+ }
+ if ($active->{refnum} == $number) {
+ unshift @display, map { my $cpy = $_; $cpy .= '_active'; $cpy }
+ grep { !/_visible$/ } @display;
+ }
+ $display = (grep { length $_ }
+ map { $displays{$_} //= _get_format(set $_) }
+ @display)[0];
+ $cdisplay = $name_format;
+ $name = as_uni($win->get_active_name) // '';
+ $name = '*' if $S{banned_on} and exists $banned_channels{lc1459($name)};
+ $name = remove_uniform_vars($win, $name) if $name ne '*';
+ if ($name ne '*' and $win->{name} ne '' and $S{prefer_name}) {
+ $name = as_uni($win->{name});
+ if ($custom_xform) {
+ no strict 'refs';
+ local ${ __PACKAGE__ . '::custom_xform::NAME' } = 1;
+ run_custom_xform() for $name;
+ }
+ }
+
+ if (!$VIEWER_MODE && $S{block} >= 0 && $S{hide_name}
+ && $win->{data_level} < abs $S{hide_name}
+ && ($win->{refnum} != $active->{refnum} || 0 <= $S{hide_name})) {
+ $name = '';
+ $cdisplay = '';
+ }
+ }
+
+ $display = "$display%n";
+ my $num_ent = (' 'x max(0,$numPad - length $number)) . $number;
+ my $key_ent = exists $keymap{$number} ? ((' 'x max(0,$keyPad - length $keymap{$number})) . $keymap{$number}) : ' 'x$keyPad;
+ if ($VIEWER_MODE or $S{sbar_maxlen} or $S{block} < 0) {
+ my $baseLength = sb_length(_format_display(
+ '', $display, $cdisplay, $hilight,
+ 'x', # placeholder
+ $num_ent,
+ $key_ent,
+ $win)) - 1;
+ my $diff = (abs $S{block}) - (screen_length(as_tc($name)) + $baseLength);
+ if ($diff < 0) { # too long
+ my $screen_length = screen_length(as_tc($name));
+ if ((abs $diff) >= $screen_length) { $name = '' } # forget it
+ elsif ((abs $diff) + screen_length(as_tc(substr($name, 0, 1))) >= $screen_length) { $name = substr($name, 0, 1); }
+ else {
+ my $ulen = length $name;
+ my $middle2 = exists $abbrevList->{$name} ?
+ ($S{fancy_strict}) ?
+ 2* $abbrevList->{$name} :
+ (2*($abbrevList->{$name} + $ulen) / 3) :
+ ($S{fancy_head}) ?
+ 2*$ulen :
+ $ulen;
+ my $first = 1;
+ while (length $name > 1) {
+ my $cp = $middle2 >= 0 ? $middle2/2 : -1; # clearing position
+ my $rm = 2;
+ # if character at end is wider than 1 cell -> replace it with ~
+ if (screen_length(as_tc(substr $name, $cp, 1)) > 1) {
+ if ($first || $cp < 0) {
+ $rm = 1;
+ $first = undef;
+ }
+ }
+ elsif ($cp < 0) { # elsif at end -> replace last 2 characters
+ --$cp;
+ }
+ (substr $name, $cp, $rm) = $abbrev1;
+ if ($cp > -1 && $rm > 1) {
+ --$middle2;
+ }
+ my $sl = screen_length(as_tc($name));
+ if ($sl + $baseLength < abs $S{block}) {
+ (substr $name, ($middle2+1)/2, 1) = $abbrev2;
+ last;
+ }
+ elsif ($sl + $baseLength == abs $S{block}) {
+ last;
+ }
+ }
+ }
+ }
+ elsif ($VIEWER_MODE or $S{block} < 0) {
+ $name .= (' ' x $diff);
+ }
+ }
+
+ push @win_items, _format_display(
+ '', $display, $cdisplay, $hilight,
+ as_tc($name),
+ $num_ent,
+ as_tc($key_ent),
+ $win);
+
+ if ($global_tag_header_mode) {
+ $last_net = $backup_win->{active}{server}{tag};
+ redo;
+ }
+
+ $mouse_coords{refnum}{$#win_items} = $number;
+ }
+}
+
+sub _spread_items {
+ my $width = $screenWidth - $sb_base_width - 1;
+ my @separator = _get_format(set 'separator');
+ if ($S{block} >= 0) {
+ my $sep2 = _get_format(set 'separator2');
+ push @separator, $sep2 if length $sep2 && $sep2 ne $separator[0];
+ }
+ $separator[0] .= '%n';
+ my @sepLen = map { sb_length($_) } @separator;
+
+ @actString = ();
+ my $curLine;
+ my $curLen = 0;
+ if ($S{shared_sbar}) {
+ $curLen += $S{shared_sbar}[0] + 2;
+ $width -= $S{shared_sbar}[2];
+ }
+ my $mouse_header_check = 0;
+ for my $it (@win_items) {
+ my $itemLen = sb_length($it);
+ if ($curLen) {
+ if ($curLen + $itemLen + $sepLen[$mouse_header_check % @sepLen] > $width) {
+ $width += $S{shared_sbar}[2]
+ if !@actString && $S{shared_sbar};
+ push @actString, $curLine;
+ $curLine = undef;
+ $curLen = 0;
+ }
+ elsif (defined $curLine) {
+ $curLine .= $separator[$mouse_header_check % @separator];
+ $curLen += $sepLen[$mouse_header_check % @sepLen];
+ }
+ }
+ $curLine .= $it;
+ if (exists $mouse_coords{refnum}{$mouse_header_check}) {
+ $mouse_coords{scalar @actString}{ $_ } = $mouse_coords{refnum}{$mouse_header_check}
+ for $curLen .. $curLen + $itemLen - 1;
+ }
+ $curLen += $itemLen;
+ }
+ continue {
+ ++$mouse_header_check;
+ }
+ $curLen -= $S{shared_sbar}[0]
+ if !@actString && $S{shared_sbar};
+ push @actString, $curLine if $curLen;
+}
+
+sub remake {
+ my %abbrevList;
+ my @wins = window_list();
+ if ($VIEWER_MODE or $S{sbar_maxlen} or $S{block} < 0) {
+ _calculate_abbrev(\@wins, \%abbrevList);
+ }
+
+ %mouse_coords = ( refnum => +{} );
+ _calculate_items(\@wins, \%abbrevList);
+
+ unless ($VIEWER_MODE) {
+ _spread_items();
+
+ push @actString, undef unless @actString || $S{all_disable};
+ }
+}
+
+sub update_wl {
+ return if $BLOCK_ALL;
+ remake();
+
+ Irssi::statusbar_items_redraw(set $_) for keys %statusbars;
+
+ unless ($VIEWER_MODE) {
+ Irssi::timeout_add_once(100, 'syncLines', undef);
+ }
+ else {
+ syncViewer();
+ }
+}
+
+sub screenFullRedraw {
+ my ($window) = @_;
+ if (!ref $window or $window->{refnum} == Irssi::active_win->{refnum}) {
+ $viewer{fullRedraw} = 1 if $viewer{client};
+ $settings_str = '';
+ &setup_changed;
+ }
+}
+
+sub restartViewerServer {
+ if ($VIEWER_MODE) {
+ stop_viewer();
+ start_viewer();
+ }
+}
+
+sub _simple_quote {
+ my @r = map {
+ my $x = $_;
+ $x =~ s/'/'"'"'/g;
+ $x = "'$x'";
+ } @_;
+ wantarray ? @r : shift @r
+}
+
+sub _viewer_command_replace_format {
+ my ($ecmd, @args) = @_;
+ my $file = _simple_quote(SCRIPT_FILE());
+ my $path = _simple_quote($viewer{path});
+ my @env;
+ for my $env (shellwords($S{viewer_launch_env})) {
+ if ($env =~ /^(\w+)(?:=(.*))$/) {
+ push @env, "AWL_$1=$2"
+ }
+ }
+ my $cmd = join ' ',
+ (@env ? ('env', _simple_quote(@env)) : ()),
+ 'perl', $file, '-1', _simple_quote(@args), $path;
+ $ecmd =~ s{%(%|\w+)}{
+ my $sub = $1;
+ if ($sub eq '%') {
+ '%'
+ }
+ elsif ($sub =~ /^(q*)A(.*)/) {
+ my $ret = $cmd;
+ for (1..length $1) {
+ $ret = _simple_quote($ret);
+ }
+ "$ret$2"
+ }
+ else {
+ "%$sub"
+ }
+ }gex;
+ $ecmd
+}
+
+sub start_viewer {
+ unlink $viewer{path} if -S $viewer{path} || -p _;
+
+ $viewer{server} = IO::Socket::UNIX->new(
+ Type => SOCK_STREAM,
+ Local => $viewer{path},
+ Listen => 1
+ );
+ unless ($viewer{server}) {
+ $viewer{msg} = "Viewer: $!";
+ $viewer{retry} = Irssi::timeout_add_once(5000, 'retry_viewer', 1);
+ return;
+ }
+ $viewer{server}->blocking(0);
+ set_viewer_mode_hint();
+ $viewer{server_tag} = Irssi::input_add($viewer{server}->fileno, INPUT_READ, 'vi_connected', undef);
+
+ if ($S{viewer_launch}) {
+ if (length $ENV{TMUX_PANE} && length $ENV{TMUX} && lc $S{viewer_tmux_position} ne 'custom') {
+ my $cmd = _viewer_command_replace_format('%qA', '-p', lc $S{viewer_tmux_position});
+ Irssi::command("exec - tmux neww -d $cmd 2>&1 &");
+ }
+ elsif (length $ENV{WINDOWID} && length $ENV{DISPLAY} && length $S{viewer_xwin_command} && $S{viewer_xwin_command} =~ /\S/) {
+ my $cmd = _viewer_command_replace_format($S{viewer_xwin_command});
+ Irssi::command("exec - $cmd 2>&1 &");
+ }
+ elsif (length $S{viewer_custom_command} && $S{viewer_custom_command} =~ /\S/) {
+ my $cmd = _viewer_command_replace_format($S{viewer_custom_command});
+ Irssi::command("exec - $cmd 2>&1 &");
+ }
+ }
+}
+
+sub set_viewer_mode_hint {
+ return unless $viewer{server};
+ if ($S{no_mode_hint}) {
+ $viewer{msg} = undef;
+ }
+ else {
+ my ($name) = __PACKAGE__ =~ /::([^:]+)$/;
+ $viewer{msg} = "Run $name from the shell or switch to sbar mode";
+ }
+}
+
+sub retry_viewer {
+ start_viewer();
+}
+
+sub vi_close_client {
+ Irssi::input_remove(delete $viewer{client_tag}) if exists $viewer{client_tag};
+ $viewer{client}->close if $viewer{client};
+ delete $viewer{client};
+ delete $viewer{client_keymap};
+ delete $viewer{client_settings};
+ delete $viewer{client_env};
+ delete $viewer{fullRedraw};
+}
+
+sub vi_connected {
+ vi_close_client();
+ $viewer{client} = $viewer{server}->accept or return;
+ $viewer{client}->blocking(0);
+ $viewer{client_tag} = Irssi::input_add($viewer{client}->fileno, INPUT_READ, 'vi_clientinput', undef);
+ syncViewer();
+}
+
+use constant VIEWER_BLOCK_SIZE => 1024;
+sub vi_clientinput {
+ if ($viewer{client}->read(my $buf, VIEWER_BLOCK_SIZE)) {
+ $viewer{rcvbuf} .= $buf;
+ if ($viewer{rcvbuf} =~ s/^(?:(active|\d+)|(last|up|down))\n//igm) {
+ if (defined $2) {
+ Irssi::command("window $2");
+ }
+ elsif (lc $1 eq 'active' && $viewer{use_ack}) {
+ Irssi::command($viewer{use_ack});
+ }
+ else {
+ Irssi::command("window goto $1");
+ }
+ }
+ }
+ else {
+ vi_close_client();
+ Irssi::timeout_add_once(100, 'syncViewer', undef);
+ }
+}
+
+sub stop_viewer {
+ Irssi::timeout_remove(delete $viewer{retry}) if exists $viewer{retry};
+ vi_close_client();
+ Irssi::input_remove(delete $viewer{server_tag}) if exists $viewer{server_tag};
+ return unless $viewer{server};
+ $viewer{server}->close;
+ delete $viewer{server};
+}
+sub _encode_var {
+ my $str;
+ while (@_) {
+ my ($name, $var) = splice @_, 0, 2;
+ my $type = ref $var ? $var =~ /HASH/ ? 'map' : $var =~ /ARRAY/ ? 'list' : '' : '';
+ $str .= "\n\U$name$type\_begin\n";
+ if ($type eq 'map') {
+ no warnings 'numeric';
+ $str .= " $_\n ${$var}{$_}\n" for sort { $a <=> $b || $a cmp $b } keys %$var;
+ }
+ elsif ($type eq 'list') {
+ $str .= " $_\n" for @$var;
+ }
+ else {
+ $str .= " $var\n";
+ }
+ $str .= "\U$name$type\_end\n";
+ }
+ $str
+}
+sub syncViewer {
+ if ($viewer{client}) {
+ @actString = ();
+ if ($currentLines) {
+ killOldStatus();
+ $currentLines = 0;
+ }
+ my $str;
+ unless ($viewer{client_keymap}) {
+ $str .= _encode_var('key', +{ %nummap, %specialmap });
+ $viewer{client_keymap} = 1;
+ }
+ unless ($viewer{client_settings}) {
+ $str .= _encode_var(
+ block => $S{block},
+ ha => $S{height_adjust},
+ mc => $S{maxcolumns},
+ ml => $S{maxlines},
+ tc => $S{true_colour},
+ );
+ $viewer{client_settings} = 1;
+ }
+ unless ($viewer{client_env}) {
+ $str .= _encode_var(irssienv => +{
+ length $ENV{TMUX_PANE} && length $ENV{TMUX} ?
+ (tmux_pane => $ENV{TMUX_PANE},
+ tmux_srv => $ENV{TMUX}) : (),
+ length $ENV{WINDOWID} ?
+ (xwinid => $ENV{WINDOWID}) : (),
+ });
+ $viewer{client_env} = 1;
+ }
+ my $separator = _get_format(set 'separator');
+ my $sepLen = sb_length($separator);
+ my $item_bg = _get_format(set 'viewer_item_bg');
+ my $title = _get_format(set 'title');
+ if (length $title) {
+ $title =~ s{\\(.)|(.)}{
+ defined $2 ? quotemeta $2
+ : $1 eq 'V' ? '\U'
+ : $1 eq ':' ? quotemeta '%N'
+ : $1 =~ /^[uUFQE]$/ ? "\\$1"
+ : quotemeta "\\$1"
+ }sge;
+ $title = eval qq{"$title"};
+ }
+ $str .= _encode_var(redraw => 1) if delete $viewer{fullRedraw};
+ $str .= _encode_var(separator => $separator,
+ seplen => $sepLen,
+ itembg => $item_bg,
+ title => $title,
+ mouse => $mouse_coords{refnum},
+ key2 => \%wnmap_exp,
+ win => \@win_items);
+
+ my $was = $viewer{client}->blocking(1);
+ $viewer{client}->print($str);
+ $viewer{client}->blocking($was);
+ }
+ elsif ($viewer{server}) {
+ if (defined $viewer{msg}) {
+ @actString = ((uc setc()).": $viewer{msg}");
+ }
+ else {
+ @actString = ();
+ }
+ }
+ elsif (defined $viewer{msg}) {
+ @actString = ((uc setc()).": $viewer{msg}");
+ }
+ if (@actString) {
+ Irssi::timeout_add_once(100, 'syncLines', undef);
+ }
+ elsif ($currentLines) {
+ killOldStatus();
+ $currentLines = 0;
+ }
+}
+
+sub reset_awl {
+ Irssi::timeout_remove($shade_line_timer) if $shade_line_timer; $shade_line_timer = undef;
+ my $was_sort = $S{sort} // '';
+ my $was_xform = $S{xform} // '';
+ my $was_shared = $S{shared_sbar};
+ my $was_no_hint = $S{no_mode_hint};
+ my $was_custom_key = $S{custom_key_re} // '';
+ %S = (
+ sort => Irssi::settings_get_str( set 'sort'),
+ fancy_abbrev => Irssi::settings_get_str('fancy_abbrev'),
+ xform => Irssi::settings_get_str( set 'custom_xform'),
+ block => Irssi::settings_get_int( set 'block'),
+ banned_on => Irssi::settings_get_bool('banned_channels_on'),
+ prefer_name => Irssi::settings_get_bool(set 'prefer_name'),
+ hide_data => Irssi::settings_get_int( set 'hide_data'),
+ hide_name => Irssi::settings_get_int( set 'hide_name_data'),
+ hide_empty => Irssi::settings_get_int( set 'hide_empty'),
+ custom_key_re => Irssi::settings_get_str( set 'custom_key_re'),
+ detach => Irssi::settings_get_str( set 'detach'),
+ detach_data => Irssi::settings_get_int( set 'detach_data'),
+ detach_aht => Irssi::settings_get_bool(set 'detach_aht'),
+ sbar_maxlen => Irssi::settings_get_bool(set 'sbar_maxlength'),
+ placement => Irssi::settings_get_str( set 'placement'),
+ position => Irssi::settings_get_int( set 'position'),
+ maxlines => Irssi::settings_get_int( set 'maxlines'),
+ maxcolumns => Irssi::settings_get_int( set 'maxcolumns'),
+ all_disable => Irssi::settings_get_bool(set 'all_disable'),
+ height_adjust => Irssi::settings_get_int( set 'height_adjust'),
+ mouse_offset => Irssi::settings_get_int( set 'mouse_offset'),
+ mouse_scroll => Irssi::settings_get_int( 'mouse_scroll'),
+ mouse_escape => Irssi::settings_get_int( 'mouse_escape'),
+ line_shade => Irssi::settings_get_time(set 'last_line_shade'),
+ no_mode_hint => Irssi::settings_get_bool(set 'no_mode_hint'),
+ true_colour => Irssi::parse_special('$colors_ansi_24bit'),
+ viewer_launch => Irssi::settings_get_bool(set 'viewer_launch'),
+ viewer_launch_env => Irssi::settings_get_str(set 'viewer_launch_env'),
+ viewer_xwin_command => Irssi::settings_get_str(set 'viewer_xwin_command'),
+ viewer_custom_command => Irssi::settings_get_str(set 'viewer_custom_command'),
+ viewer_tmux_position => Irssi::settings_get_str(set 'viewer_tmux_position'),
+ );
+ $S{fancy_strict} = $S{fancy_abbrev} =~ /^strict/i;
+ $S{fancy_head} = $S{fancy_abbrev} =~ /^head/i;
+ my $shared = Irssi::settings_get_str(set 'shared_sbar');
+ if ($shared =~ /^(\d+)([<])(\d+)$/) {
+ $S{shared_sbar} = [$1, $2, $3];
+ }
+ else {
+ Irssi::settings_set_str(set 'shared_sbar', 'OFF');
+ $S{shared_sbar} = undef;
+ }
+ lock_keys(%S);
+ if ($was_sort ne $S{sort}) {
+ $print_text_activity = undef;
+ my @sort_order = grep { @$_ > 4 } map {
+ s/^\s*//;
+ my $reverse = s/^\W*\K[-!]//;
+ my $undef_check = s/^\W*\K~// ? 1 : undef;
+ my $equal_check = s/=(.*)\s?$// ? $1 : undef;
+ s/\s*$//;
+ my $ignore_case = s/#i$// ? 1 : undef;
+
+ $print_text_activity = 1 if $_ eq 'last_line';
+
+ my @path = split '/';
+ my $class_check = @path && $path[-1] =~ s/(::.*)$// ? $1 : undef;
+ my $lru = "@path" eq 'lru';
+
+ [ $reverse ? -1 : 1, $undef_check, $equal_check, $class_check, $ignore_case, $lru, @path ]
+ } "$S{sort}," =~ /([^+,]*|[^+,]*=[^,]*?\s(?=\+)|[^+,]*=[^,]*)[+,]/g;
+ $window_sort_func = sub {
+ no warnings qw(numeric uninitialized);
+ for my $so (@sort_order) {
+ my @x = map {
+ my $ret = 0;
+ $_ = lc1459($_) if defined $_ && !ref $_ && $so->[4];
+ $ret = $_ eq ($so->[4] ? lc1459($so->[2]) : $so->[2]) ? 1 : -1 if defined $so->[2];
+ $ret = defined $_ ? ($ret || -3) : 3 if $so->[1];
+ $ret = ref $_ && $_->isa('Irssi'.$so->[3]) ? 2 : ($ret || -2) if $so->[3];
+ -$ret || $_
+ }
+ map {
+ $so->[5] ? $_->[0] : reduce { return unless ref $a; $a->{$b} } $_->[1], @{$so}[6..$#$so]
+ } $a, $b;
+ return ((($x[0] <=> $x[1] || $x[0] cmp $x[1]) * $so->[0]) || next);
+ }
+ return ($a->[1]{refnum} <=> $b->[1]{refnum});
+ };
+ }
+ if ($was_xform ne $S{xform}) {
+ if ($S{xform} !~ /\S/) {
+ $custom_xform = undef;
+ }
+ else {
+ my $script_pkg = __PACKAGE__ . '::custom_xform';
+ local $@;
+ $custom_xform = eval qq{
+package $script_pkg;
+use strict;
+no warnings;
+our (\$QUERY, \$CHANNEL, \$TAG, \$NAME);
+return sub {
+# line 1 @{[ set 'custom_xform' ]}\n$S{xform}\n}};
+ if ($@) {
+ $@ =~ /^(.*)/;
+ print '%_'.(set 'custom_xform').'%_ did not compile: '.$1;
+ }
+ }
+ }
+ if ($was_custom_key ne $S{custom_key_re}) {
+ my $custom_key = $S{custom_key_re};
+ my $was_custom_key_re = $custom_key_re;
+ local $@;
+ eval { $custom_key_re = qr/(?i)$custom_key/; 1 }
+ or do {
+ print '%_'.(set 'custom_key_re').'%_ did not compile: '
+ . do { $@ =~ /(.*) at / && $1 };
+ $custom_key_re = qr/(?!)/;
+ };
+ if ($was_custom_key_re ne $custom_key_re) {
+ update_keymap();
+ }
+ }
+
+ my $new_settings = join "\n", $VIEWER_MODE
+ ? ("\\", $S{block}, $S{height_adjust}, $S{maxlines}, $S{maxcolumns}, $S{true_colour})
+ : ("!", $S{placement}, $S{position});
+
+ my $first_viewer = $settings_str eq '1';
+ if ($settings_str ne $new_settings) {
+ @actString = ();
+ %abbrev_cache = ();
+ $currentLines = 0;
+ killOldStatus();
+ delete $viewer{client_settings};
+ $settings_str = $new_settings;
+ }
+
+ my $was_mouse_mode = $MOUSE_ON;
+ if ($MOUSE_ON = Irssi::settings_get_bool(set 'mouse') and !$was_mouse_mode) {
+ install_mouse();
+ }
+ elsif ($was_mouse_mode and !$MOUSE_ON) {
+ uninstall_mouse();
+ }
+
+ unless ($first_viewer) {
+ my $path = Irssi::settings_get_str(set 'path');
+ my $was_viewer_mode = $VIEWER_MODE;
+ if ($was_viewer_mode &&
+ defined $viewer{path} && $viewer{path} ne $path) {
+ stop_viewer();
+ $was_viewer_mode = 0;
+ }
+ elsif ($was_viewer_mode && $S{no_mode_hint} != $was_no_hint + 0) {
+ set_viewer_mode_hint();
+ }
+ $viewer{path} = $path;
+ if ($VIEWER_MODE = Irssi::settings_get_bool(set 'viewer') and !$was_viewer_mode) {
+ start_viewer();
+ }
+ elsif ($was_viewer_mode and !$VIEWER_MODE) {
+ stop_viewer();
+ }
+ }
+
+ %banned_channels = map { lc1459(as_uni($_)) => undef }
+ split ' ', Irssi::settings_get_str('banned_channels');
+
+ %detach_map = ($S{detach_aht}
+ ? (map { ( lc1459(as_uni($_)) => undef ) }
+ split ' ', Irssi::settings_get_str('activity_hide_targets')) : (),
+ (map { my ($k, $v) = (split /(?:,(-?\d+))$/, $_)[0, 1];
+ ( lc1459(as_uni($k)) => $v ) }
+ split ' ', $S{detach}));
+
+ my @sb_base = split /\177/, sb_format_expand("{sbstart}{sb \177}{sbend}"), 2;
+ $sb_base_width_pre = sb_length($sb_base[0]);
+ $sb_base_width_post = max 0, sb_length($sb_base[1])-1;
+ $sb_base_width = $sb_base_width_pre + $sb_base_width_post;
+
+ if ($print_text_activity && $S{line_shade}) {
+ $shade_line_timer = Irssi::timeout_add(max(10 * GLOB_QUEUE_TIMER, 100*$S{line_shade}**(1/3)), 'wl_changed', undef);
+ }
+
+ $CHANGED{AWINS} = 1;
+}
+
+sub hide_window {
+ my ($data) = @_;
+ my $ent;
+
+ $data =~ s/\s*$//;
+ my $win = Irssi::active_win;
+ my $number = $win->{refnum};
+ my $name = as_uni($win->{name});
+ my $active = as_uni($win->get_active_name) // '';
+ my $tag = $win->{active} && $win->{active}{server} ? as_uni($win->{active}{server}{tag}) // '' : '';
+ if (length $name) {
+ $ent = "$name";
+ }
+ elsif (length $tag && length $active) {
+ $ent = "$tag/$active";
+ }
+ else {
+ $ent = "$number";
+ }
+
+ my $found = 0;
+ my @setting;
+ for my $s (split ' ', $S{detach}) {
+ my ($k, $v) = (split /(?:,(-?\d+))$/, $s)[0, 1];
+ if (lc1459(as_uni($k)) eq lc1459($ent)) {
+ unless ($found) {
+ if ($data =~ /^(-?\d+)$/) {
+ $ent .= ",$1";
+ }
+ if (defined $v && 0 == abs $v) {
+ $win->print("Hiding window $ent");
+ }
+ push @setting, as_tc($ent);
+ $found = 1;
+ }
+ }
+ else {
+ push @setting, defined $v ? "$k,$v" : $k;
+ }
+ }
+ unless ($found) {
+ $win->print("Hiding window $ent");
+ if ($data =~ /^(-?\d+)$/) {
+ $ent .= ",$1";
+ }
+ push @setting, as_tc($ent);
+ }
+
+ if (@setting) {
+ Irssi::command("^set ".(set 'detach')." @setting");
+ } else {
+ Irssi::command("^set -clear ".(set 'detach'));
+ }
+}
+
+sub unhide_window {
+ my ($data, $server, $witem) = @_;
+ my $win = Irssi::active_win;
+ my $number = $win->{refnum};
+ my $name = as_uni($win->{name});
+ my $active = as_uni($win->get_active_name) // '';
+ my $tag = $win->{active} && $win->{active}{server} ? as_uni($win->{active}{server}{tag}) // '' : '';
+
+ my %detach_aht;
+ if ($S{detach_aht}) {
+ %detach_aht = (map { ( lc1459(as_uni($_)) => undef ) }
+ split ' ', Irssi::settings_get_str('activity_hide_targets'));
+ }
+ my @setting;
+ my @kills = (length $name ? $name : undef,
+ length $tag && length $active ? "$tag/$active" : undef,
+ length $active ? $active : undef,
+ $number);
+ my @was_unhidden = (0) x @kills;
+ for my $s (split ' ', $S{detach}) {
+ my ($k, $v) = (split /(?:,(-?\d+))$/, $s)[0, 1];
+ my $k2 = lc1459(as_uni($k));
+ my $kill;
+ for my $ki (0..$#kills) {
+ if (defined $kills[$ki] && $k2 eq lc1459($kills[$ki])) {
+ $kill = $ki;
+ }
+ }
+
+ if (defined $kill) {
+ if (defined $v && 0 == abs $v) {
+ $was_unhidden[$kill] = 1;
+ push @setting, defined $v ? "$k,$v" : $k;
+ } else {
+ $win->print("Unhiding window $kills[$kill]");
+ }
+ }
+ else {
+ push @setting, defined $v ? "$k,$v" : $k;
+ }
+ }
+ my @is_hidden = (defined $kills[0] && (exists $detach_map{"*"} || exists $detach_map{"::all"}),
+ defined $kills[1] && (exists $detach_map{lc1459("$tag/*")} || exists $detach_map{lc1459("$tag/::all")}
+ || exists $detach_map{"*"} || exists $detach_map{"::all"}),
+ defined $kills[2] && (exists $detach_map{"*"} || exists $detach_map{"::all"}),
+ (exists $detach_map{"*"} || exists $detach_map{"::all"})
+ );
+ for my $ki (1, 2, 0, 3) {
+ if ($is_hidden[$ki]) {
+ unless ($was_unhidden[$ki]) {
+ $win->print("Unhiding window $kills[$ki]");
+ push @setting, "$kills[$ki],0";
+ $was_unhidden[$ki] = 1;
+ }
+ last;
+ }
+ }
+ my @is_hidden_aht = (defined $kills[0] && (exists $detach_aht{lc1459($name)}
+ || exists $detach_aht{"*"} || exists $detach_aht{"::all"}),
+ defined $kills[1] && (exists $detach_aht{lc1459("$tag/$active")}
+ || exists $detach_aht{lc1459($active)}
+ || exists $detach_aht{lc1459("$tag/*")} || exists $detach_aht{lc1459("$tag/::all")}
+ || exists $detach_aht{"*"} || exists $detach_aht{"::all"}),
+ defined $kills[2] && (exists $detach_aht{lc1459($active)}
+ || exists $detach_aht{"*"} || exists $detach_aht{"::all"}),
+ (exists $detach_aht{$number} || exists $detach_aht{"*"} || exists $detach_aht{"::all"})
+ );
+ for my $ki (1, 2, 0, 3) {
+ if ($is_hidden_aht[$ki]) {
+ unless ($was_unhidden[$ki]) {
+ $win->print("Unhiding window $kills[$ki], it is hidden because ".(set 'detach_aht')." is ON");
+ push @setting, "$kills[$ki],0";
+ $was_unhidden[$ki] = 1;
+ }
+ last;
+ }
+ }
+
+ if (@setting) {
+ Irssi::command("^set ".(set 'detach')." @setting");
+ } else {
+ Irssi::command("^set -clear ".(set 'detach'));
+ }
+}
+
+sub ack_window {
+ my ($data, $server, $witem) = @_;
+ my $win = Irssi::active_win;
+ my $number = $win->{refnum};
+ if (grep { $_->{cmd} eq 'ack' } Irssi::commands) {
+ my $Orig_Irssi_windows = \&Irssi::windows;
+ local *Irssi::windows = sub () { grep { !_is_detached($_, $number) } $Orig_Irssi_windows->() };
+ Irssi::command("ack" . (length $data ? " $data" : ""));
+ } else {
+ my $ignore_refnum = Irssi::settings_get_bool('active_window_ignore_refnum');
+ my $max_win;
+ my $max_act = 0;
+ my $max_ref = 0;
+ for my $rec (Irssi::windows) {
+ next if _is_detached($rec, $number);
+
+ # ignore refnum
+ if ($ignore_refnum &&
+ $rec->{data_level} > 0 && $max_act < $rec->{data_level}) {
+ $max_act = $rec->{data_level};
+ $max_win = $rec;
+ }
+
+ # windows with lower refnums break ties
+ elsif (!$ignore_refnum &&
+ $rec->{data_level} > 0 &&
+ ($rec->{data_level} > $max_act ||
+ ($rec->{data_level} == $max_act && $rec->{refnum} < $max_ref))) {
+ $max_act = $rec->{data_level};
+ $max_win = $rec;
+ $max_ref = $rec->{refnum};
+ }
+ }
+ $max_win->set_active if defined $max_win;
+ }
+}
+
+sub refnum_changed {
+ my ($win, $old_refnum) = @_;
+ my @old_setting = split ' ', $S{detach};
+ my @setting = map {
+ my ($k, $v) = (split /(?:,(-?\d+))$/, $_)[0, 1];
+ if ($k eq $old_refnum) {
+ $win->{refnum} . (defined $v ? ",$v" : "")
+ }
+ else {
+ $_
+ }
+ } @old_setting;
+ if ("@old_setting" ne "@setting") {
+ $S{detach} = "@setting";
+ Irssi::settings_set_str(set 'detach', "@setting");
+ &setup_changed;
+ }
+ else {
+ &wl_changed;
+ }
+}
+
+sub window_destroyed {
+ my ($win) = @_;
+ my @old_setting = split ' ', $S{detach};
+ my @setting = grep {
+ my ($k, $v) = (split /(?:,(-?\d+))$/, $_)[0, 1];
+ if ($k eq $win->{refnum}) {
+ 0;
+ }
+ else {
+ 1;
+ }
+ } @old_setting;
+ if ("@old_setting" ne "@setting") {
+ $S{detach} = "@setting";
+ Irssi::settings_set_str(set 'detach', "@setting");
+ &setup_changed;
+ }
+ else {
+ &awins_changed;
+ }
+}
+
+sub stop_mouse_tracking {
+ print STDERR "\e[?1005l\e[?1000l";
+}
+sub start_mouse_tracking {
+ print STDERR "\e[?1000h\e[?1005h";
+}
+sub install_mouse {
+ Irssi::command_bind('mouse_xterm' => 'mouse_xterm');
+ Irssi::command('^bind meta-[M command mouse_xterm');
+ Irssi::signal_add_first('gui key pressed' => 'mouse_key_hook');
+ start_mouse_tracking();
+}
+sub uninstall_mouse {
+ stop_mouse_tracking();
+ Irssi::signal_remove('gui key pressed' => 'mouse_key_hook');
+ Irssi::command('^bind -delete meta-[M');
+ Irssi::command_unbind('mouse_xterm' => 'mouse_xterm');
+}
+
+sub awl_mouse_event {
+ return if $VIEWER_MODE;
+ if ((($_[0] == 3 and $_[3] == 0)
+ || $_[0] == 64 || $_[0] == 65) and
+ $_[1] == $_[4] and $_[2] == $_[5]) {
+ my $top = lc $S{placement} eq 'top';
+ my ($pos, $line) = @_[1 .. 2];
+ unless ($top) {
+ $line -= $screenHeight;
+ $line += $currentLines;
+ $line += $S{mouse_offset};
+ }
+ else {
+ $line -= $S{mouse_offset};
+ }
+ $pos -= $sb_base_width_pre;
+ return if $line < 0 || $line >= $currentLines;
+ if ($_[0] == 64) {
+ Irssi::command('window up');
+ }
+ elsif ($_[0] == 65) {
+ Irssi::command('window down');
+ }
+ elsif (exists $mouse_coords{$line}{$pos}) {
+ my $win = $mouse_coords{$line}{$pos};
+ Irssi::command('window ' . $win);
+ }
+ Irssi::signal_stop;
+ }
+}
+
+sub mouse_scroll_event {
+ return unless $S{mouse_scroll};
+ if (($_[3] == 64 or $_[3] == 65) and
+ $_[0] == $_[3] and $_[1] == $_[4] and $_[2] == $_[5]) {
+ my $cmd = 'scrollback goto ' . ($_[3] == 64 ? '-' : '+') . $S{mouse_scroll};
+ Irssi::active_win->command($cmd);
+ Irssi::signal_stop;
+ }
+ elsif ($_[0] == 64 or $_[0] == 65) {
+ Irssi::signal_stop;
+ }
+}
+
+sub mouse_escape {
+ return unless $S{mouse_escape} > 0;
+ if ($_[0] == 3) {
+ my $tm = $S{mouse_escape};
+ $tm *= 1000 if $tm < 1000;
+ stop_mouse_tracking();
+ Irssi::timeout_add_once($tm, 'start_mouse_tracking', undef);
+ Irssi::signal_stop;
+ }
+}
+
+sub UNLOAD {
+ @actString = ();
+ killOldStatus();
+ stop_viewer() if $VIEWER_MODE;
+ uninstall_mouse() if $MOUSE_ON;
+}
+
+sub addPrintTextHook { # update on print text
+ return unless defined $^S;
+ return if $BLOCK_ALL;
+ return unless $print_text_activity;
+ return if $_[0]->{level} == MSGLEVEL_CLIENTNOTICE and $_[0]->{target} eq ''
+ and !defined($_[0]->{server});
+ &wl_changed;
+}
+
+sub block_event_window_change {
+ Irssi::signal_stop;
+}
+
+sub update_awins {
+ my @wins = Irssi::windows;
+ local $BLOCK_ALL = 1;
+ Irssi::signal_add_first('window changed' => 'block_event_window_change');
+ my $bwin =
+ my $awin = Irssi::active_win;
+ my $lwin;
+ my $defer_irssi_broken_last;
+ unless ($wins[0]{refnum} == $awin->{refnum}) {
+ # special case: more than 1 last win, so /win last;
+ # /win last doesn't come back to the current window. eg. after
+ # connect & autojoin; we can't handle this situation, bail out
+ $defer_irssi_broken_last = 1;
+ }
+ else {
+ $awin->command('window last');
+ $lwin = Irssi::active_win;
+ $lwin->command('window last');
+ $defer_irssi_broken_last = $lwin->{refnum} == $bwin->{refnum};
+ }
+ my $awin_counter = 0;
+ Irssi::signal_remove('window changed' => 'block_event_window_change');
+ unless ($defer_irssi_broken_last) {
+ # we need to keep the fe-windows code running here
+ Irssi::signal_add_priority('window changed' => 'block_event_window_change', -99);
+ %awins = %wnmap_exp = ();
+ do {
+ Irssi::active_win->command('window up');
+ $awin = Irssi::active_win;
+ $awins{$awin->{refnum}} = undef;
+ ++$awin_counter;
+ } until ($awin->{refnum} == $bwin->{refnum} || $awin_counter >= @wins);
+ Irssi::signal_remove('window changed' => 'block_event_window_change');
+
+ Irssi::signal_add_first('window changed' => 'block_event_window_change');
+ for my $key (keys %wnmap) {
+ next unless Irssi::window_find_name($key) || Irssi::window_find_item($key);
+ $awin->command("window goto $key");
+ my $cwin = Irssi::active_win;
+ $wnmap_exp{ $cwin->{refnum} } = $wnmap{$key};
+ $cwin->command('window last')
+ if $cwin->{refnum} != $awin->{refnum};
+ }
+ for my $win (reverse @wins) { # restore original window order
+ Irssi::active_win->command('window '.$win->{refnum});
+ }
+ $awin->command('window '.$lwin->{refnum}); # restore last win
+ Irssi::active_win->command('window last');
+ Irssi::signal_remove('window changed' => 'block_event_window_change');
+ }
+ $CHANGED{WL} = 1;
+}
+
+sub resizeTerm {
+ if (defined (my $r = `stty size 2>/dev/null`)) {
+ ($screenHeight, $screenWidth) = split ' ', $r;
+ $CHANGED{SETUP} = 1;
+ }
+ else {
+ $CHANGED{SIZE} = 1;
+ }
+}
+
+sub awl_refresh {
+ $globTime = undef;
+ resizeTerm() if delete $CHANGED{SIZE};
+ reset_awl() if delete $CHANGED{SETUP};
+ update_awins() if delete $CHANGED{AWINS};
+ update_wl() if delete $CHANGED{WL};
+}
+
+sub termsize_changed { $CHANGED{SIZE} = 1; &queue_refresh; }
+sub setup_changed { $CHANGED{SETUP} = 1; &queue_refresh; }
+sub awins_changed { $CHANGED{AWINS} = 1; &queue_refresh; }
+sub wl_changed { $CHANGED{WL} = 1; &queue_refresh; }
+
+sub window_changed {
+ &awins_changed if $_[1];
+}
+
+sub queue_refresh {
+ return if $BLOCK_ALL;
+ Irssi::timeout_remove($globTime)
+ if defined $globTime; # delay the update further
+ $globTime = Irssi::timeout_add_once(GLOB_QUEUE_TIMER, 'awl_refresh', undef);
+}
+
+sub awl_init {
+ termsize_changed();
+ setup_changed();
+ update_keymap();
+ Irssi::timeout_remove($globTime)
+ if defined $globTime;
+ awl_refresh();
+ termsize_changed();
+}
+
+sub runsub {
+ my $cmd = shift;
+ sub {
+ my ($data, $server, $item) = @_;
+ Irssi::command_runsub($cmd, $data, $server, $item);
+ };
+}
+
+Irssi::signal_register({
+ 'gui mouse' => [qw/int int int int int int/],
+ });
+{ my $broken_expandos = (Irssi::version >= 20081128 && Irssi::version < 20110210)
+ ? sub { my $x = shift; $x =~ s/\$\{cumode_space\}/ /; $x } : undef;
+ Irssi::theme_register([
+ map { $broken_expandos ? $broken_expandos->($_) : $_ }
+ set 'display_nokey' => '$N${cumode_space}$H$C$S',
+ set 'display_key' => '$Q${cumode_space}$H$C$S',
+ set 'display_nokey_visible' => '%2$N${cumode_space}$H$C$S',
+ set 'display_key_visible' => '%2$Q${cumode_space}$H$C$S',
+ set 'display_nokey_active' => '%1$N${cumode_space}$H$C$S',
+ set 'display_key_active' => '%1$Q${cumode_space}$H$C$S',
+ set 'display_header' => '%8$C|${N}',
+ set 'name_display' => '$0',
+ set 'separator' => ' ',
+ set 'separator2' => '',
+ set 'abbrev_chars' => "~\x{301c}",
+ set 'viewer_item_bg' => sb_format_expand('{sb_background}'),
+ set 'title' => '\V'.setc().'\:',
+ ]);
+}
+Irssi::settings_add_bool(setc, set 'prefer_name', 0); #
+Irssi::settings_add_int( setc, set 'hide_empty', 0); #
+Irssi::settings_add_int( setc, set 'hide_data', 0); #
+Irssi::settings_add_str( setc, set 'detach', ''); #
+Irssi::settings_add_int( setc, set 'detach_data', -3); #
+Irssi::settings_add_bool(setc, set 'detach_aht', 0); #
+Irssi::settings_add_int( setc, set 'hide_name_data', 0); #
+Irssi::settings_add_int( setc, set 'maxlines', 9); #
+Irssi::settings_add_int( setc, set 'maxcolumns', 4); #
+Irssi::settings_add_int( setc, set 'block', 15); #
+Irssi::settings_add_bool(setc, set 'sbar_maxlength', 1); #
+Irssi::settings_add_int( setc, set 'height_adjust', 2); #
+Irssi::settings_add_str( setc, set 'sort', 'refnum'); #
+Irssi::settings_add_str( setc, set 'placement', 'bottom'); #
+Irssi::settings_add_int( setc, set 'position', 0); #
+Irssi::settings_add_bool(setc, set 'all_disable', 1); #
+Irssi::settings_add_bool(setc, set 'viewer', 1); #
+Irssi::settings_add_str( setc, set 'shared_sbar', 'OFF'); #
+Irssi::settings_add_bool(setc, set 'mouse', 0); #
+Irssi::settings_add_str( setc, set 'path', Irssi::get_irssi_dir . '/_windowlist'); #
+Irssi::settings_add_str( setc, set 'custom_xform', ''); #
+Irssi::settings_add_str( setc, set 'custom_key_re', 'f\d+'); #
+Irssi::settings_add_time(setc, set 'last_line_shade', '0'); #
+Irssi::settings_add_int( setc, set 'mouse_offset', 1); #
+Irssi::settings_add_int( setc, 'mouse_scroll', 3); #
+Irssi::settings_add_int( setc, 'mouse_escape', 1); #
+Irssi::settings_add_str( setc, 'banned_channels', '');
+Irssi::settings_add_bool(setc, 'banned_channels_on', 1);
+Irssi::settings_add_str( setc, 'fancy_abbrev', 'fancy'); #
+Irssi::settings_add_bool(setc, set 'no_mode_hint', 0); #
+Irssi::settings_add_bool(setc, set 'viewer_launch', 1); #
+Irssi::settings_add_str( setc, set 'viewer_launch_env', ''); #
+Irssi::settings_add_str( setc, set 'viewer_tmux_position', 'left'); #
+Irssi::settings_add_str( setc, set 'viewer_xwin_command', 'xterm +sb -e %A'); #
+Irssi::settings_add_str( setc, set 'viewer_custom_command', ''); #
+
+Irssi::signal_add_last({
+ 'setup changed' => 'setup_changed',
+ 'print text' => 'addPrintTextHook',
+ 'terminal resized' => 'termsize_changed',
+ 'setup reread' => 'screenFullRedraw',
+ 'window hilight' => 'wl_changed',
+ 'command format' => 'wl_changed',
+});
+Irssi::signal_add({
+ 'window changed' => 'window_changed',
+ 'window item changed' => 'wl_changed',
+ 'window changed automatic' => 'window_changed',
+ 'window created' => 'awins_changed',
+ 'window destroyed' => 'window_destroyed',
+ 'window name changed' => 'wl_changed',
+ 'window refnum changed' => 'refnum_changed',
+});
+Irssi::signal_add_last('gui mouse' => 'mouse_escape');
+Irssi::signal_add_last('gui mouse' => 'mouse_scroll_event');
+Irssi::signal_add_last('gui mouse' => 'awl_mouse_event');
+Irssi::command_bind( setc() => runsub(setc()) );
+Irssi::command_bind( setc() . ' redraw' => 'screenFullRedraw' );
+Irssi::command_bind( setc() . ' restart' => 'restartViewerServer' );
+Irssi::command_bind( setc() . ' attach' => 'unhide_window' );
+Irssi::command_bind( setc() . ' detach' => 'hide_window' );
+Irssi::command_bind( setc() . ' ack' => 'ack_window' );
+
+{
+ my $l = set 'shared';
+ {
+ no strict 'refs';
+ *{$l} = $awl_shared_empty;
+ }
+ Irssi::statusbar_item_register($l, '$0', $l);
+}
+
+awl_init();
+
+# Mouse script based on irssi mouse patch by mirage
+{ my $mouse_status = -1; # -1:off 0,1,2:filling mouse_combo
+ my @mouse_combo = (-1, -1, -1); # 0:button 1:x 2:y
+ my @mouse_previous = (-1, -1, -1); # previous contents of mouse_combo
+
+ sub mouse_xterm_off {
+ $mouse_status = -1;
+ }
+ sub mouse_xterm {
+ $mouse_status = 0;
+ Irssi::timeout_add_once(10, 'mouse_xterm_off', undef);
+ }
+
+ sub mouse_key_hook {
+ my ($key) = @_;
+ if ($mouse_status != -1) {
+ if ($mouse_status == 0) {
+ @mouse_previous = @mouse_combo;
+ #if @mouse_combo && $mouse_combo[0] < 64;
+ }
+ $mouse_combo[$mouse_status] = $key - 32;
+ $mouse_status++;
+ if ($mouse_status == 3) {
+ $mouse_status = -1;
+ # match screen coordinates
+ $mouse_combo[1]--;
+ $mouse_combo[2]--;
+ Irssi::signal_emit('gui mouse', @mouse_combo[0 .. 2], @mouse_previous[0 .. 2]);
+ }
+ Irssi::signal_stop;
+ }
+ }
+}
+
+sub string_LCSS {
+ my $str = join "\0", @_;
+ (sort { length $b <=> length $a } $str =~ /(?=(.+).*\0.*\1)/g)[0]
+}
+
+# workaround for issue #271
+{ package Irssi::Nick }
+
+# workaround for issue #572
+@Irssi::UI::Exec::ISA = 'Irssi::Windowitem'
+ if Irssi::version >= 20140822 && Irssi::version <= 20161101 && !@Irssi::UI::Exec::ISA;
+
+UNITCHECK
+{ package AwlViewer;
+ use strict;
+ use warnings;
+ no warnings 'redefine';
+ use Encode;
+ use IO::Socket::UNIX;
+ use IO::Select;
+ use List::Util qw(max);
+ use constant BLOCK_SIZE => 1024;
+ use constant RECONNECT_TIME => 5;
+
+ my $sockpath;
+
+ our $VERSION = '0.8';
+
+ our ($got_int, $resized, $timeout);
+
+ my %vars;
+ my (%c2w, @seqlist);
+ my %mouse_coords;
+ my (@mouse, @last_mouse);
+ my ($err, $sock, $loop);
+ my ($keybuf, $rcvbuf);
+ my @screen;
+ my ($screenHeight, $screenWidth);
+ my ($disp_update, $fs_open, $one_shot_integration, $one_shot_resize);
+ my $integration_position;
+ my $show_title_bar;
+
+ sub connect_it {
+ $sock = IO::Socket::UNIX->new(
+ Type => SOCK_STREAM,
+ Peer => $sockpath,
+ );
+ unless ($sock) {
+ $err = $!;
+ return;
+ }
+ $sock->blocking(0);
+ $loop->add($sock);
+ }
+
+ sub remove_conn {
+ my $fh = shift;
+ $loop->remove($fh);
+ $fh->close;
+ $sock = undef;
+ %vars = ();
+ @screen = ();
+ }
+
+ { package Terminfo; # xterm
+ sub civis { "\e[?25l" }
+ sub sc { "\e7" }
+ sub cup { "\e[" . ($_[0] + 1) . ';' . ($_[1] + 1) . 'H' }
+ sub el { "\e[K" }
+ sub rc { "\e8" }
+ sub cnorm { "\e[?25h" }
+ sub setab { "\e[4" . $_[0] . 'm' }
+ sub setaf { "\e[3" . $_[0] . 'm' }
+ sub setaf16 { "\e[9" . $_[0] . 'm' }
+ sub setab16 { "\e[10" . $_[0] . 'm' }
+ sub setaf256 { "\e[38;5;" . $_[0] . 'm' }
+ sub setab256 { "\e[48;5;" . $_[0] . 'm' }
+ sub setafrgb { "\e[38;2;" . $_[0] . ';' . $_[1] . ';' . $_[2] . 'm' }
+ sub setabrgb { "\e[48;2;" . $_[0] . ';' . $_[1] . ';' . $_[2] . 'm' }
+ sub sgr0 { "\e[0m" }
+ sub bold { "\e[1m" }
+ sub it { "\e[3m" }
+ sub ul { "\e[4m" }
+ sub blink { "\e[5m" }
+ sub rev { "\e[7m" }
+ sub op { "\e[39;49m" }
+ sub exit_bold { "\e[22m" }
+ sub exit_it { "\e[23m" }
+ sub exit_ul { "\e[24m" }
+ sub exit_blink { "\e[25m" }
+ sub exit_rev { "\e[27m" }
+ sub smcup { "\e[?1049h" }
+ sub rmcup { "\e[?1049l" }
+ sub smmouse { "\e[?1000h\e[?1005h" }
+ sub rmmouse { "\e[?1005l\e[?1000l" }
+ }
+
+ sub init {
+ $sockpath = shift // "$ENV{HOME}/.irssi/_windowlist";
+ STDOUT->autoflush(1);
+ printf "\r%swaiting for %s...", Terminfo::sc, $::IRSSI{name};
+
+ `stty -icanon -echo`;
+
+ $loop = IO::Select->new;
+ STDIN->blocking(0);
+ $loop->add(\*STDIN);
+
+ $SIG{INT} = sub {
+ $got_int = 1
+ };
+ $SIG{WINCH} = sub {
+ $resized = 1
+ };
+
+ $resized = 3;
+
+ $disp_update = 2;
+
+ $show_title_bar = 1;
+ }
+
+ sub enter_fs {
+ return if $fs_open;
+ safe_print(Terminfo::rc, Terminfo::smcup, Terminfo::civis, Terminfo::smmouse);
+ $fs_open = 1;
+ }
+
+ sub leave_fs {
+ return unless $fs_open;
+ safe_print(Terminfo::rmmouse, Terminfo::cnorm, Terminfo::rmcup);
+ safe_print(sprintf "\r%swaiting for %s...", Terminfo::sc, $::IRSSI{name}) if $_[0];
+
+ $fs_open = 0;
+ }
+
+ sub end_prog {
+ leave_fs();
+ STDIN->blocking(1);
+ `stty sane`;
+ printf "\r%s%sthanks for using %s\n", Terminfo::rc, Terminfo::el, $::IRSSI{name};
+ }
+
+ sub safe_print {
+ my $st = STDIN->blocking(1);
+ print @_;
+ STDIN->blocking($st);
+ }
+
+ sub safe_qx {
+ my $st = STDIN->blocking(1);
+ my $ret = `$_[0]`;
+ STDIN->blocking($st);
+ $ret
+ }
+
+ sub safe_print_sock {
+ return unless $sock;
+ my $was = $sock->blocking(1);
+ $sock->print(@_);
+ $sock->blocking($was);
+ }
+
+ sub process_recv {
+ my $need = 0;
+ while ($rcvbuf =~ s/\n(.+)_BEGIN\n((?: .*\n)*)\1_END\n//) {
+ my $var = lc $1;
+ my $data = $2;
+ my @data = split "\n ", "\n$data ", -1;
+ shift @data; pop @data;
+ my $itembg = $vars{itembg};
+ if ($var =~ s/list$//) {
+ $vars{$var} = \@data;
+ }
+ elsif ($var =~ s/map$//) {
+ $vars{$var} = +{ @data };
+ }
+ else {
+ $vars{$var} = join "\n", @data;
+ }
+ $need = 1 if $var eq 'win';
+ $need = 1 if $var eq 'redraw' && $vars{$var};
+ if (($itembg//'') ne ($vars{itembg}//'')) {
+ $need = $vars{redraw} = 1;
+ }
+ _build_keymap() if $var eq 'key2';
+ }
+ $need
+ }
+
+ { my %ansi_table;
+ my ($i, $j, $k) = (0, 0, 0);
+ my %term_state;
+ sub reset_term_state { my %old_term = %term_state; %term_state = (); %old_term }
+ sub set_term_state { my %old_term = %term_state; %term_state = @_; %old_term }
+ %ansi_table = (
+ # fe-common::core::formats.c:format_expand_styles
+ (map { my $t = $i++; ($_ => sub { my $n = $term_state{hicolor} ? \&Terminfo::setab16 : \&Terminfo::setab;
+ $n->($t) }) } (split //, '01234567' )),
+ (map { my $t = $j++; ($_ => sub { my $n = $term_state{hicolor} ? \&Terminfo::setaf16 : \&Terminfo::setaf;
+ $n->($t) }) } (split //, 'krgybmcw' )),
+ (map { my $t = $k++; ($_ => sub { my $n = $term_state{hicolor} ? \&Terminfo::setaf : \&Terminfo::setaf16;
+ $n->($t) }) } (split //, 'KRGYBMCW')),
+ # reset
+ n => sub { $term_state{hicolor} = 0; my $r = Terminfo::op;
+ for (qw(blink rev bold)) {
+ $r .= Terminfo->can("exit_$_")->() if delete $term_state{$_};
+ }
+ {
+ local $ansi_table{n} = $ansi_table{N};
+ $r .= formats_to_ansi_basic($vars{itembg});
+ }
+ $r
+ },
+ N => sub { reset_term_state(); Terminfo::sgr0 },
+ # flash/bright
+ F => sub { my $n = 'blink'; my $e = ($term_state{$n} ^= 1) ? $n : "exit_$n"; Terminfo->can($e)->() },
+ # reverse
+ 8 => sub { my $n = 'rev'; my $e = ($term_state{$n} ^= 1) ? $n : "exit_$n"; Terminfo->can($e)->() },
+ # bold
+ "_" => sub { my $n = 'bold'; my $e = ($term_state{$n} ^= 1) ? $n : "exit_$n"; Terminfo->can($e)->() },
+ # underline
+ U => sub { my $n = 'ul'; my $e = ($term_state{$n} ^= 1) ? $n : "exit_$n"; Terminfo->can($e)->() },
+ # italic
+ I => sub { my $n = 'it'; my $e = ($term_state{$n} ^= 1) ? $n : "exit_$n"; Terminfo->can($e)->() },
+ # bold, used as colour modifier if AWL_HI9 is set
+ 9 => $ENV{AWL_HI9} ? sub { $term_state{hicolor} ^= 1; '' }
+ : sub { my $n = 'bold'; my $e = ($term_state{$n} ^= 1) ? $n : "exit_$n"; Terminfo->can($e)->() },
+ # delete other stuff
+ (map { $_ => sub { '' } } (split //, ':|>#[')),
+ # escape
+ (map { my $close = $_; $_ => sub { $close } } (split //, '{}%')),
+ );
+ for my $base (0 .. 15) {
+ my $close = $base;
+ my $idx = ($close&8) | ($close&4)>>2 | ($close&2) | ($close&1)<<2;
+ $ansi_table{ (sprintf "x0%x", $close) } =
+ $ansi_table{ (sprintf "x0%X", $close) } =
+ sub { Terminfo::setab256($idx) };
+ $ansi_table{ (sprintf "X0%x", $close) } =
+ $ansi_table{ (sprintf "X0%X", $close) } =
+ sub { Terminfo::setaf256($idx) };
+ }
+ for my $plane (1 .. 6) {
+ for my $coord (0 .. 35) {
+ my $close = 16 + ($plane-1) * 36 + $coord;
+ my $ch = $coord < 10 ? $coord : chr( $coord - 10 + ord 'a' );
+ $ansi_table{ "x$plane$ch" } =
+ $ansi_table{ "x$plane\U$ch" } =
+ sub { Terminfo::setab256($close) };
+ $ansi_table{ "X$plane$ch" } =
+ $ansi_table{ "X$plane\U$ch" } =
+ sub { Terminfo::setaf256($close) };
+ }
+ }
+ for my $gray (0 .. 23) {
+ my $close = 232 + $gray;
+ my $ch = chr( $gray + ord 'a' );
+ $ansi_table{ "x7$ch" } =
+ $ansi_table{ "x7\U$ch" } =
+ sub { Terminfo::setab256($close) };
+ $ansi_table{ "X7$ch" } =
+ $ansi_table{ "X7\U$ch" } =
+ sub { Terminfo::setaf256($close) };
+ }
+ # fe-windows.c:color_24bit_256
+ my $cc = sub {
+ use integer;
+
+ my $cstep_size = 40;
+ my $cstep_start = 0x5f;
+
+ my $gstep_size = 10;
+ my $gstep_start = 0x08;
+
+ my @dist = (0) x 3;
+ my @r; my @gr;
+
+ for (my $i = 0; $i < 3; ++$i) {
+ my $n = $_[$i];
+ $gr[$i] = -1;
+ if ($n < $cstep_start /2) {
+ $r[$i] = 0;
+ $dist[$i] = -$cstep_size/2;
+ }
+ else {
+ $r[$i] = 1+(($n-$cstep_start + $cstep_size /2)/$cstep_size);
+ $dist[$i] = (($n-$cstep_start + $cstep_size /2)% $cstep_size - $cstep_size/2);
+ }
+ if ($n < $gstep_start /2) {
+ $gr[$i] = -1;
+ }
+ else {
+ $gr[$i] = (($n-$gstep_start + $gstep_size /2)/$gstep_size);
+ }
+ }
+ if ($r[0] == $r[1] && $r[1] == $r[2] &&
+ 4*abs($dist[0]) < $gstep_size && 4*abs($dist[1]) < $gstep_size && 4*abs($dist[2]) < $gstep_size) {
+ # skip gray detection
+ }
+ else {
+ my $j = $r[1] == $r[2] ? 0 : 1;
+ if (($r[0] == $r[1] || $r[$j] == $r[2]) && abs($r[$j]-$r[($j+1)% 3]) <= 1) {
+ my $k = $gr[1] == $gr[2] ? 0 : 1;
+ if (($gr[0] == $gr[1] || $gr[$k] == $gr[2]) && abs($gr[$k]-$gr[($k+1)% 3]) <= 2) {
+ if ($gr[$k] < 0) {
+ $r[0] = $r[1] = $r[2] = 0;
+ }
+ elsif ($gr[$k] > 23) {
+ $r[0] = $r[1] = $r[2] = 5;
+ }
+ else {
+ $r[0] = 6;
+ $r[1] = ($gr[$k] / 6);
+ $r[2] = $gr[$k]% 6;
+ }
+ }
+ }
+ }
+ return 16 + $r[0]*36 + $r[1] * 6 + $r[2];
+ };
+ $ansi_table{z} = sub {
+ my ($r, $g, $b) = map { hex } unpack '(A2)*', $_[0];
+ $vars{tc} eq 'ON' ? Terminfo::setabrgb($r, $g, $b) : Terminfo::setab256($cc->($r, $g, $b));
+ };
+ $ansi_table{Z} = sub {
+ my ($r, $g, $b) = map { hex } unpack '(A2)*', $_[0];
+ $vars{tc} eq 'ON' ? Terminfo::setafrgb($r, $g, $b) : Terminfo::setaf256($cc->($r, $g, $b));
+ };
+ sub formats_to_ansi_basic {
+ my $o = shift;
+ $o =~ s{(%((Z|z)(......)|X..|x..|.))}{
+ if ($ansi_table{$2}) { $ansi_table{$2}->() }
+ elsif ($ansi_table{$3}) { $ansi_table{$3}->($4) }
+ else { $1 }
+ }gex;
+ $o
+ }
+ }
+
+ sub _header {
+ my $str = $vars{title} // uc ::setc();
+ my $ccs = qr/%(?:Z(?:[0-9A-F]{6})|X(?:[1-6][0-9A-Z]|7[A-X])|[0-9BCFGIKMNRUWY_])/i;
+ (my $stripstr = $str) =~ s/($ccs)//g;
+ my $space = int( ((abs $vars{block}) - length $stripstr) / (1 + length $stripstr));
+ if ($space > 0) {
+ my $ss = ' ' x $space;
+ my @x = $str =~ /((?:$ccs)*\X(?:(?:$ccs)*$)?)/g;
+ $str = join $ss, '', @x, '';
+ }
+ ($stripstr = $str) =~ s/($ccs)//g;
+ my $pad = max 0, (abs $vars{block}) - length $stripstr;
+ $str = ' ' x ($pad/2) . $str . ' ' x ($pad/2 + $pad%2);
+ $str
+ }
+
+ sub _add_item {
+ my ($i, $j, $c, $wi, $screen, $mouse) = @_;
+ $screen->[$i][$j] = "%N%n$wi";
+ if (exists $vars{mouse}{$c - 1}) {
+ $mouse->[$i][$j] = $vars{mouse}{$c - 1};
+ }
+ }
+ sub update_screen {
+ $disp_update = 0;
+ unless ($sock && exists $vars{seplen} && exists $vars{block}) {
+ leave_fs(1);
+ return;
+ }
+ enter_fs();
+ @screen = () if delete $vars{redraw};
+ %mouse_coords = ();
+ my $ncols = ($vars{seplen} + abs $vars{block}) ?
+ int( ($screenWidth + $vars{seplen}) / ($vars{seplen} + abs $vars{block}) ) : 0;
+ my $xenl = ($vars{seplen} + abs $vars{block})
+ && $ncols > int( ($screenWidth + $vars{seplen} - 1) / ($vars{seplen} + abs $vars{block}) );
+ my $nrows = $screenHeight - $vars{ha};
+ my @wi = @{$vars{win}//[]};
+ my $max_items = $ncols * $nrows;
+ my $c = $show_title_bar ? 1 : 0;
+ my $items = @wi + $c;
+ my $titems = $items > $max_items ? $max_items : $items;
+ my $i = 0;
+ my $j = 0;
+ my @new_screen;
+ my @new_mouse;
+ $new_screen[0][0] = _header() #. ' ' x $vars{seplen}
+ if $show_title_bar;
+ unless ($nrows > $ncols) { # line layout
+ ++$j if $show_title_bar;
+ for my $wi (@wi) {
+ if ($j >= $ncols) {
+ $j = 0;
+ ++$i;
+ }
+ last if $i >= $nrows;
+ _add_item($i, $j, $show_title_bar ? $c : $c + 1,
+ $wi, \@new_screen, \@new_mouse);
+ if ($c + 1 < $titems && $j + 1 < $ncols) {
+ $new_screen[$i][$j] .= $vars{separator};
+ }
+ ++$j;
+ ++$c;
+ }
+ }
+ else { # column layout
+ ++$i if $show_title_bar;
+ for my $wi (@wi) {
+ if ($i >= $nrows) {
+ $i = 0;
+ ++$j;
+ }
+ last if $j >= $ncols;
+ _add_item($i, $j, $show_title_bar ? $c : $c + 1,
+ $wi, \@new_screen, \@new_mouse);
+ if ($c + $nrows < $titems) {
+ $new_screen[$i][$j] .= $vars{separator};
+ }
+ ++$i;
+ ++$c;
+ }
+ }
+ my $step = $vars{seplen} + abs $vars{block};
+ $i = 0;
+ my $str = Terminfo::sc . Terminfo::sgr0;
+ for (my $i = 0; $i < @new_screen; ++$i) {
+ for (my $j = 0; $j < @{$new_screen[$i]}; ++$j) {
+ if (defined $new_mouse[$i] && defined $new_mouse[$i][$j]) {
+ my $from = $j * $step;
+ $mouse_coords{$i}{$_} = $new_mouse[$i][$j]
+ for $from .. $from + abs $vars{block};
+ }
+ next if defined $screen[$i] && defined $screen[$i][$j]
+ && $screen[$i][$j] eq $new_screen[$i][$j];
+ $str .= Terminfo::cup($i, $j * $step)
+ . formats_to_ansi_basic($new_screen[$i][$j])
+ . Terminfo::sgr0;
+ $str .= Terminfo::el if $j == $#{$new_screen[$i]} && (!$xenl || $j + 1 != $ncols);
+ }
+ }
+ for (@new_screen .. $screenHeight - 1) {
+ if (!@screen || defined $screen[$_]) {
+ $str .= Terminfo::cup($_, 0) . Terminfo::sgr0 . Terminfo::el;
+ }
+ }
+ $str .= Terminfo::rc;
+ safe_print $str;
+ @screen = @new_screen;
+ }
+
+ sub handle_resize {
+ if (defined (my $r = safe_qx('stty size'))) {
+ ($screenHeight, $screenWidth) = split ' ', $r;
+ $resized = 0;
+ @screen = ();
+ $disp_update = 1;
+ if ($one_shot_integration == 2) {
+ $one_shot_resize--;
+ }
+ }
+ else {
+ }
+ }
+
+ sub _build_keymap {
+ %c2w = reverse( %{$vars{key}}, %{$vars{key2}} );
+ if (!grep { /^[+-]./ } keys %c2w) {
+ %c2w = (%c2w, map { ("-$_" => $c2w{$_}) } grep { !/^\^./ } keys %c2w);
+ }
+ %c2w = map {
+ my $key = $_;
+ s{^(-)?(\+)?(\^)?(.)}{
+ join '', (
+ ($1 ? "\e" : ''),
+ ($2 ? "\e\e" : ''),
+ ($3 ? "$4"^"@" : $4)
+ )
+ }e;
+ $_ => $c2w{$key}
+ } keys %c2w;
+ @seqlist = sort { length $b <=> length $a } keys %c2w;
+ }
+
+ sub _match_tmux {
+ length $ENV{TMUX} && exists $vars{irssienv}{tmux_srv} && length $vars{irssienv}{tmux_pane}
+ && $ENV{TMUX} eq $vars{irssienv}{tmux_srv}
+ }
+
+ sub process_keys {
+ Encode::_utf8_on($keybuf);
+ my $win;
+ my $use_mouse;
+ my $maybe;
+ KEY: while (length $keybuf && !$maybe) {
+ $maybe = 0;
+ if ($keybuf =~ s/^\e\[M(.)(.)(.)//) {
+ @last_mouse = @mouse;# if @mouse && $mouse[0] < 64;
+ @mouse = map { -32 + ord } ($1, $2, $3);
+ $use_mouse = 1;
+ next KEY;
+ }
+ for my $s (@seqlist) {
+ if ($keybuf =~ s/^\Q$s//) {
+ $win = $c2w{$s};
+ $use_mouse = 0;
+ next KEY;
+ }
+ elsif (length $keybuf < length $s && $s =~ /^\Q$keybuf/) {
+ $maybe = 1;
+ }
+ }
+ unless ($maybe) {
+ substr $keybuf, 0, 1, '';
+ }
+ }
+ if ($use_mouse && @mouse && @last_mouse &&
+ $mouse[2] == $last_mouse[2] &&
+ $mouse[1] == $last_mouse[1] &&
+ ($mouse[0] == 3 || $mouse[0] == 64 || $mouse[0] == 65)) {
+ if ($mouse[0] == 64) {
+ $win = 'up';
+ }
+ elsif ($mouse[0] == 65) {
+ $win = 'down';
+ }
+ elsif (exists $mouse_coords{$mouse[2] - 1}{$mouse[1] - 1}) {
+ $win = $mouse_coords{$mouse[2] - 1}{$mouse[1] - 1};
+ }
+ elsif ($mouse[2] == 1 && $mouse[1] <= abs $vars{block}) {
+ $win = $last_mouse[0] != 0 ? 'last' : 'active';
+ }
+ else {
+ }
+ }
+ if (defined $win) {
+ $win =~ s/^_//;
+ safe_print_sock("$win\n");
+ if (!exists $ENV{AWL_AUTOFOCUS} || $ENV{AWL_AUTOFOCUS}) {
+ if (_match_tmux()) {
+ safe_qx("tmux selectp -t $vars{irssienv}{tmux_pane} 2>&1");
+ }
+ elsif (exists $vars{irssienv}{xwinid}) {
+ safe_qx("wmctrl -ia $vars{irssienv}{xwinid} 2>/dev/null");
+ }
+ }
+ }
+ Encode::_utf8_off($keybuf);
+ }
+
+ sub check_integration {
+ return unless $vars{irssienv};
+ return unless $sock && exists $vars{seplen} && exists $vars{block};
+ if ($one_shot_integration == 1) {
+ my $nrows = $screenHeight - $vars{ha};
+ my $ncols = ($vars{seplen} + abs $vars{block}) ? int( ($screenWidth + $vars{seplen}) / ($vars{seplen} + abs $vars{block}) ) : 0;
+ my $items = ($show_title_bar ? 1 : 0) + @{$vars{win}//[]};
+ my $dcols_required = $nrows ? int($items/$nrows) + !!($items%$nrows) : 0;
+ my $rows_required = $ncols ? int($items/$ncols) + !!($items%$ncols) : 0;
+ $rows_required = abs $vars{ml}
+ if ($vars{ml} < 0 || ($vars{ml} > 0 && $rows_required > $vars{ml}));
+ $dcols_required = abs $vars{mc}
+ if ($vars{mc} < 0 || ($vars{mc} > 0 && $dcols_required > $vars{mc}));
+ my $rows = $rows_required + $vars{ha};
+ my $cols = ($dcols_required * ($vars{seplen} + abs $vars{block})) - $vars{seplen};
+ if (_match_tmux()) {
+ # int( ($screenWidth + $vars{seplen}) / ($vars{seplen} + abs $vars{block}) );
+ my ($pos_flag, $before);
+ if ($integration_position eq 'left') {
+ $pos_flag = 'h';
+ $before = 1;
+ }
+ elsif ($integration_position eq 'top') {
+ $pos_flag = 'v';
+ $before = 1;
+ }
+ elsif ($integration_position eq 'right') {
+ $pos_flag = 'h';
+ }
+ else {
+ $pos_flag = 'v';
+ }
+ my @cmd = "joinp -d$pos_flag -s $ENV{TMUX_PANE} -t $vars{irssienv}{tmux_pane}";
+ push @cmd, "swapp -d -t $ENV{TMUX_PANE} -s $vars{irssienv}{tmux_pane}"
+ if $before;
+ $cols = max($cols, 2);
+ $rows = max($rows, 2);
+
+ safe_qx("tmux " . (join " \\\; ", @cmd) . " 2>&1");
+ }
+ else {
+ $resized = 1;
+ #safe_qx("resize -s $screenHeight $cols 2>&1")
+ # if $cols > 0;
+ }
+ $one_shot_integration++;
+ if ($resized == 1) {
+ handle_resize();
+ resize_integration();
+ }
+ }
+ elsif ($one_shot_integration == 2) {
+ resize_integration(1);
+ }
+ }
+
+ sub resize_integration {
+ return unless $one_shot_integration;
+ return unless ($one_shot_resize//0) < 0 || shift;
+ return if ($one_shot_resize//0) > 0;
+
+ my $nrows = $screenHeight - $vars{ha};
+ my $ncols = ($vars{seplen} + abs $vars{block}) ? int( ($screenWidth + $vars{seplen}) / ($vars{seplen} + abs $vars{block}) ) : 0;
+ my $items = ($show_title_bar ? 1 : 0) + @{$vars{win}//[]};
+ my $dcols_required = $nrows ? (int($items/$nrows) + !!($items%$nrows)) : 0;
+ my $rows_required = $ncols ? int($items/$ncols) + !!($items%$ncols) : 0;
+ $rows_required = abs $vars{ml}
+ if ($vars{ml} < 0 || ($vars{ml} > 0 && $rows_required > $vars{ml}));
+ $dcols_required = abs $vars{mc}
+ if ($vars{mc} < 0 || ($vars{mc} > 0 && $dcols_required > $vars{mc}));
+ my $rows = $rows_required + $vars{ha};
+ my $cols = ($dcols_required * ($vars{seplen} + abs $vars{block})) - $vars{seplen};
+ if (_match_tmux()) {
+ my $pos_flag;
+ my $before = 0;
+ if ($integration_position eq 'left') {
+ $pos_flag = 'h';
+ $before = 1;
+ }
+ elsif ($integration_position eq 'top') {
+ $pos_flag = 'v';
+ $before = 1;
+ }
+ elsif ($integration_position eq 'right') {
+ $pos_flag = 'h';
+ }
+ else {
+ $pos_flag = 'v';
+ }
+ my @cmd;
+ # hard tmux limits
+ $cols = max($cols, 2);
+ $rows = max($rows, 2);
+ if ($pos_flag eq 'h' && $cols != $screenWidth) {
+ my $change = $screenWidth - $cols;
+ my $dir = ($before ^ ($change<0)) ? 'L' : 'R';
+ push @cmd, "resizep -$dir -t $ENV{TMUX_PANE} @{[abs $change]}";
+ #push @cmd, "resizep -x $cols -t $ENV{TMUX_PANE}";
+ $one_shot_resize = 1;
+ }
+ if ($pos_flag eq 'v' && $rows != $screenHeight) {
+ #push @cmd, "resizep -y $rows -t $ENV{TMUX_PANE}";
+ my $change = $screenHeight - $rows;
+ my $dir = ($before ^ ($change<0)) ? 'U' : 'D';
+ push @cmd, "resizep -$dir -t $ENV{TMUX_PANE} @{[abs $change]}";
+ $one_shot_resize = 1;
+ }
+
+ safe_qx("tmux " . (join " \\\; ", @cmd) . " 2>&1")
+ if @cmd;
+ }
+ else {
+ $cols = max($cols, 1);
+ $rows = max($rows, 1);
+ unless ($nrows > $ncols) { # line layout
+ if ($rows != $screenHeight) {
+ safe_qx("resize -s $rows $screenWidth 2>&1");
+ $one_shot_resize = 1;
+ }
+ }
+ else {
+ if ($cols != $screenWidth) {
+ safe_qx("resize -s $screenHeight $cols 2>&1");
+ $one_shot_resize = 1;
+ }
+ }
+ }
+ if ($resized == 1) {
+ handle_resize();
+ }
+ }
+
+ sub init_integration {
+ return unless $one_shot_integration;
+ if (_match_tmux()) {
+ }
+ else {
+ }
+ safe_print("\e]2;".(uc ::setc())."\e\\");
+ }
+
+ sub main {
+ require Getopt::Std;
+ my %opts;
+ Getopt::Std::getopts('1p:', \%opts);
+ my $one_shot = $opts{1};
+ $integration_position = $opts{p};
+ $one_shot_integration = 0+!!$one_shot;
+ #shift if @_ && $_[0] eq '--';
+ &init;
+ $show_title_bar = 0 if $ENV{AWL_NOTITLE};
+ init_integration();
+ until ($got_int) {
+ $timeout = undef;
+ if ($resized) {
+ if ($resized == 1) {
+ $timeout = 1;
+ $resized++;
+ }
+ else {
+ handle_resize();
+ resize_integration();
+ }
+ }
+ unless ($sock || $timeout) {
+ connect_it();
+ }
+ $timeout ||= RECONNECT_TIME unless $sock;
+ update_screen() if $disp_update;
+ SELECT: while (my @read = $loop->can_read($timeout)) {
+ for my $fh (@read) {
+ if ($fh == \*STDIN) {
+ if (read STDIN, my $buf, BLOCK_SIZE) {
+ do {
+ $keybuf .= $buf;
+ } while read STDIN, $buf, BLOCK_SIZE;
+ }
+ else {
+ $got_int = 1;
+ last SELECT;
+ }
+ }
+ else {
+ if ($fh->read(my $buf, BLOCK_SIZE)) {
+ do {
+ $rcvbuf .= $buf;
+ } while $fh->read($buf, BLOCK_SIZE);
+ }
+ else {
+ $disp_update = 1;
+ remove_conn($fh);
+ if ($one_shot) {
+ $got_int = 1;
+ last SELECT;
+ }
+ $timeout ||= RECONNECT_TIME;
+ }
+ }
+ }
+ $disp_update |= process_recv() if length $rcvbuf;
+ process_keys() if length $keybuf;
+ check_integration() if $one_shot;
+ update_screen() if $disp_update;
+ }
+ continue {
+ }
+ }
+ end_prog();
+ }
+}
+
+1;
+
+# Changelog
+# =========
+# 1.11
+# - fix compat with Irssi 1.4
+#
+# 1.10
+# - add /set awl_custom_key_re, to display custom keys in the $Q
+# expando. requested by madduck
+#
+# 1.9.1
+# - fix crash on mouse click
+#
+# 1.9
+# - add %Z support to viewer
+#
+# 1.8
+# - use string_width in Irssi 1.2.0
+#
+# 1.7
+# - fix crash on invalid /set awl_sort, introduced in 1.6, reported by
+# tpetazzoni
+# - delay viewer initialisation
+# - improve race condition on tmux resize integration
+#
+# 1.6
+# - add detach setting to hide windows
+# - fix race condition when loading the script, reported by madduck
+# - improve compatibility with irssi 1.2
+# - add special value lru to awl_sort to sort windows by usage
+#
+# 1.5
+# - improve compat. with sideways splits
+#
+# 1.4
+# - fix line wrapping in some themes, reported by justanotherbody
+# - fix named window key detection, reported by madduck
+# - make title (in viewer and shared_sbar) configurable
+#
+# 1.3
+# - workaround for irssi issue #572
+#
+# 1.2
+# - new format to choose abbreviation character
+#
+# 1.1
+# - infinite loop on shortening certain window names reported by Kalan
+#
+# 1.0
+# - new awl_viewer_launch setting and an array of related settings
+# - fixed regression bug /exec -interactive
+# - fixed some warnings in perl 5.10 reported by kl3
+# - workaround for crash due to infinite recursion in irssi's Perl
+# error handling
+#
+# 0.9
+# - fix endless loop in awin detection code!
+# - correct colour swap in awl_viewer
+# - fix passing of alternate socket path to the viewer
+# - potential undefinedness in mouse refnum hinted at by Canopus
+# - fixed regression bug /exec -interactive
+# - add case-insensitive modifier to awl_sort
+# - run custom_xform on awl_prefer_name also
+# - avoid inconsistent active window state after awin detection
+# reported by ss
+# - revert %9-hack in the viewer prompted by discussion with pierrot
+# - fix new warning in perl 5.22
+#
+# 0.8
+# - replace fifo mode with external viewer script
+# - remove bundled cpan modules
+# - work around bogus irssi warning
+# - improve mouse support
+# - workaround for broken cumode in irssi 0.8.15
+# - fix handling of non-meta windows (uninitialized warning)
+# - add 256 colour support, strip true colour codes
+# - fix totally bogus $N padding reported by Ed S.
+# - make /window goto #name mappings work but ignore non-existant ones
+# - improve incomplete reads reported by bcode
+# - fix single % in awl_viewer reported by bcode
+# - add support for key bindings by nike and ferret
+# - coerce utf8 key binds
+# - add settings: custom_xform, last_line_shade, hide_name_data
+# - abbreviations were broken in some cases
+# - fix some misuse of / as cmdchar in mouse script reported by bcode
+# - add shared status bar mode
+# - ${type} variables for custom_xform setting
+# - crash if custom_xform had runtime error
+# - update sorting documentation
+# - fix odd case in size calculation noted by lasers
+# - add missing font styles to the viewer reported by ishanyx
+# - add italic
+#
+# 0.7g
+# - remove screen support and replace it with fifo support
+# - add double-width support to the shortener
+# - correct documentation regarding $T vs. display_header
+# - add missing refresh for window item changed (thanks vague)
+# - add visible windows
+# - add exemptions for active window
+# - workaround for hiding the window changes from trackbar
+# - hack to force 16colours in screen mode
+# - remember last window (reported by earthnative)
+# - wrong window focus on new queries (reported by emsid)
+# - dataloss bug on trying to remember last window
+#
+# 0.6d+
+# - add support for network headers
+# - fixed regression bug /exec -interactive
+#
+# 0.6ca+
+# - add screen support (from nicklist.pl)
+# - names can now have a max length and window names can be used
+# - fixed a bug with block display in screen mode and status bar mode
+# - added space handling to ir_fe and removed it again
+# - now handling formats on my own
+# - started to work on $tag display
+# - added warning about missing sb_act_none abstract leading to
+# - display*active settings
+# - added warning about the bug in awl_display_(no)key_active settings
+# - mouse hack
+#
+# 0.5d
+# - add setting to also hide the last status bar if empty (awl_all_disable)
+# - reverted to old utf8 code to also calculate broken utf8 length correctly
+# - simplified dealing with status bars in wlreset
+# - added a little tweak for the renamed term_type somewhere after Irssi 0.8.9
+# - fixed bug in handling channel #$$
+# - reset background colour at the beginning of an entry
+#
+# 0.4d
+# - fixed order of disabling status bars
+# - several attempts at special chars, without any real success
+# and much more weird new bugs caused by this
+# - setting to specify sort order
+# - reduced timeout values
+# - added awl_hide_data
+# - make it so the dynamic sub is actually deleted
+# - fix a bug with removing of the last separator
+# - take into consideration parse_special
+#
+# 0.3b
+# - automatically kill old status bars
+# - reset on /reload
+# - position/placement settings
+#
+# 0.2
+# - automated retrieval of key bindings (thanks grep.pl authors)
+# - improved removing of status bars
+# - got rid of status chop
+#
+# 0.1
+# - Based on chanact.pl which was apparently based on lightbar.c and
+# nicklist.pl with various other ideas from random scripts.
diff --git a/.irssi/scripts/mouse.pl b/.irssi/scripts/mouse.pl
new file mode 100644
index 0000000..d9debc7
--- /dev/null
+++ b/.irssi/scripts/mouse.pl
@@ -0,0 +1,168 @@
+# See http://wouter.coekaerts.be/site/irssi/mouse
+# based on irssi mouse patch by mirage: http://darksun.com.pt/mirage/irssi/
+
+# Copyright (C) 2005-2009 Wouter Coekaerts <wouter@coekaerts.be>
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+use strict;
+use Irssi qw(signal_emit settings_get_str active_win signal_stop settings_add_str settings_add_bool settings_get_bool signal_add signal_add_first);
+use Math::Trig;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.1.2';
+%IRSSI = (
+ authors => 'Wouter Coekaerts',
+ contact => 'wouter@coekaerts.be',
+ name => 'mouse',
+ description => 'control irssi using mouse clicks and gestures',
+ license => 'GPLv2 or later',
+ url => 'http://wouter.coekaerts.be/irssi/',
+ changed => '2021-03-05',
+);
+
+my @BUTTONS = ('', '_middle', '_right');
+
+my $mouse_xterm_status = -1; # -1:off 0,1,2:filling mouse_xterm_combo
+my @mouse_xterm_combo = (3, 0, 0); # 0:button 1:x 2:y
+my @mouse_xterm_previous; # previous contents of mouse_xterm_combo
+
+sub mouse_enable {
+ print STDERR "\e[?1000h"; # start tracking
+}
+
+sub mouse_disable {
+ print STDERR "\e[?1000l"; # stop tracking
+}
+
+# Handle mouse event (button press or release)
+sub mouse_event {
+ my ($b, $x, $y, $oldb, $oldx, $oldy) = @_;
+ my ($xd, $yd);
+ my ($distance, $angle);
+
+ # uhm, in the patch the scrollwheel didn't work for me, but this does:
+ if ($b == 64) {
+ cmd("mouse_scroll_up");
+ } elsif ($b == 65) {
+ cmd("mouse_scroll_down")
+ }
+
+ # proceed only if a button is being released
+ return if ($b != 3);
+
+ return unless (0 <= $oldb && $oldb <= 2);
+ my $button = $BUTTONS[$oldb];
+
+ # if it was a mouse click of the left button (press and release in the same position)
+ if ($x == $oldx && $y == $oldy) {
+ cmd("mouse" . $button . "_click");
+ return;
+ }
+
+ # otherwise, find mouse gestures
+ $xd = $x - $oldx;
+ $yd = -1 * ($y - $oldy);
+ $distance = sqrt($xd*$xd + $yd*$yd);
+ # ignore small gestures
+ if ($distance < 3) {
+ return;
+ }
+ $angle = asin($yd/$distance) * 180 / 3.14159265358979;
+ if ($angle < 20 && $angle > -20 && $xd > 0) {
+ if ($distance <= 40) {
+ cmd("mouse" . $button . "_gesture_right");
+ } else {
+ cmd("mouse" . $button . "_gesture_bigright");
+ }
+ } elsif ($angle < 20 && $angle > -20 && $xd < 0) {
+ if ($distance <= 40) {
+ cmd("mouse" . $button . "_gesture_left");
+ } else {
+ cmd("mouse" . $button . "_gesture_bigleft");
+ }
+ } elsif ($angle > 40) {
+ cmd("mouse" . $button . "_gesture_up");
+ } elsif ($angle < -40) {
+ cmd("mouse" . $button . "_gesture_down");
+ }
+}
+
+# executes the command configured in the given setting
+sub cmd
+{
+ my ($setting) = @_;
+ signal_emit("send command", settings_get_str($setting), active_win->{'active_server'}, active_win->{'active'});
+}
+
+
+signal_add_first("gui key pressed", sub {
+ my ($key) = @_;
+ if ($mouse_xterm_status != -1) {
+ if ($mouse_xterm_status == 0 && ($mouse_xterm_previous[0] != $mouse_xterm_combo[0])) { # if combo is starting, and previous what not a move (button not changed)
+ @mouse_xterm_previous = @mouse_xterm_combo;
+ }
+ $mouse_xterm_combo[$mouse_xterm_status] = $key-32;
+ $mouse_xterm_status++;
+ if ($mouse_xterm_status == 3) {
+ $mouse_xterm_status = -1;
+ # match screen coordinates
+ $mouse_xterm_combo[1]--;
+ $mouse_xterm_combo[2]--;
+ mouse_event($mouse_xterm_combo[0], $mouse_xterm_combo[1], $mouse_xterm_combo[2], $mouse_xterm_previous[0], $mouse_xterm_previous[1], $mouse_xterm_previous[2]);
+ }
+ signal_stop();
+ }
+});
+
+sub UNLOAD {
+ mouse_disable();
+}
+
+if ($ENV{"TERM"} !~ /^rxvt|screen|xterm|tmux(-(256)?(color|kitty))?$/) {
+ die "Your terminal doesn't seem to support this.";
+}
+
+mouse_enable();
+
+Irssi::command("/^bind meta-[M /mouse_xterm"); # FIXME evil
+Irssi::command_bind("mouse_xterm", sub {$mouse_xterm_status = 0;});
+Irssi::command_bind 'mouse' => sub {
+ my ($data, $server, $item) = @_;
+ $data =~ s/\s+$//g;
+ Irssi::command_runsub('mouse', $data, $server, $item);
+};
+
+# temporarily disable mouse handling. Useful for copy-pasting without touching the keyboard (pressing shift)
+Irssi::command_bind 'mouse tempdisable' => sub {
+ my ($data, $server, $item) = @_;
+ my $seconds = ($data eq '') ? 5 : $data; # optional argument saying how many seconds, defaulting to 5
+ mouse_disable();
+ Irssi::timeout_add_once($seconds * 1000, 'mouse_enable', undef); # turn back on after $second seconds
+};
+
+for my $button (@BUTTONS) {
+ settings_add_str("lookandfeel", "mouse" . $button . "_click", "/mouse tempdisable 5");
+ settings_add_str("lookandfeel", "mouse" . $button . "_gesture_up", "/window last");
+ settings_add_str("lookandfeel", "mouse" . $button . "_gesture_down", "/window goto active");
+ settings_add_str("lookandfeel", "mouse" . $button . "_gesture_left", "/window prev");
+ settings_add_str("lookandfeel", "mouse" . $button . "_gesture_bigleft", "/eval window prev;window prev");
+ settings_add_str("lookandfeel", "mouse" . $button . "_gesture_right", "/window next");
+ settings_add_str("lookandfeel", "mouse" . $button . "_gesture_bigright", "/eval window next;window next");
+}
+
+settings_add_str("lookandfeel", "mouse_scroll_up", "/scrollback goto -10");
+settings_add_str("lookandfeel", "mouse_scroll_down", "/scrollback goto +10");
diff --git a/.irssi/scripts/nm2.pl b/.irssi/scripts/nm2.pl
new file mode 100644
index 0000000..b553bf2
--- /dev/null
+++ b/.irssi/scripts/nm2.pl
@@ -0,0 +1,569 @@
+use Irssi;
+use strict;
+use v5.14;
+use List::Util qw(min max);
+use Hash::Util qw(lock_keys);
+
+our $VERSION = '2.1'; # a42b713aaa38823
+our %IRSSI = (
+ authors => 'Nei',
+ contact => 'Nei @ anti@conference.jabber.teamidiot.de',
+ url => "http://anti.teamidiot.de/",
+ name => 'nm2',
+ description => 'right aligned nicks depending on longest nick',
+ license => 'GPL v2',
+);
+
+# based on bc-bd's original nm.pl
+#
+# use a ** nickcolor_expando ** script for nick colors!
+#
+# why is there no right_mode? you can do that in your theme!
+
+# Options
+# =======
+# /set neat_dynamic <ON|OFF>
+# * whether the width should be dynamically chosen on each incoming
+# message
+#
+# /set neat_shrink <ON|OFF>
+# * whether shrinking of the width is allowed, or only growing
+#
+# /set neat_staircase_shrink <ON|OFF>
+# * whether shrinking should be done one character at a time
+#
+# The following styles decide if the nick is left/right aligned and
+# where the colour/mode goes, they're a bit complex...
+# put the desired indicator(s) between the appropriate "," and the
+# default format of the public messages or actions will be rewritten
+# appropriately.
+# This can be used to align the nick left or right, before or after
+# the nick brackets and before or between the nickmode (by using the
+# pad on the correct place). To change the mode from left of the nick
+# to right of the nick, you need to modify the abstracts in your theme
+# however.
+# By placing the colour at the end, you can even colour the message
+# text in the nick colour, however it might be broken if there are
+# other colour codes used inside the message or by scripts.
+#
+# /format neat_style , , , , , , , ,
+# î î î î î î î î î
+# p: pad | | | | | | | | `before message
+# c: colour | | | | | | | `-after msgchannel
+# t: truncate indicator | | | | | | `-before msgchannel
+# | | | | | `-after nick
+# | | | | `-before nick
+# | | | `-after mode
+# | | `-before mode
+# | `-before msgnick
+# `-none
+#
+# /format neat_action_style , , , ,
+# î î î î î
+# p: pad | | | | `-before message
+# c: colour | | | `-after nick
+# t: truncate indicator | | `-before nick
+# | `-before action
+# `-none
+#
+# /format neat_pad_char <char>
+# * the character(s) used for padding
+#
+# /format neat_truncate_char
+# * the format or character to indicate that nick was truncated
+#
+# /format neat_notruncate_char
+# * the format or character to indicate that nick NOT was truncated
+#
+# /format neat_customize_modes @@ | ++ | ?
+# * a |-separated mapping of mode prefixes and their rendition, can be
+# used to replace or colourise them
+#
+# /set neat_color_hinick <ON|OFF>
+# * whether to use colours in hilighted messages
+#
+# /set neat_color_menick <ON|OFF>
+# * whether to use colours in hilight_nick_matches
+#
+# /set neat_truncate_nick <ON|OFF>
+# * whether to truncate overlong nicks
+#
+# /set neat_custom_modes <ON|OFF>
+# * whether to enable the use of neat_customize_modes format
+#
+# /set neat_maxlength <number>
+# * number : (maximum) length to use for nick padding
+#
+# /set neat_melength <number>
+# * number : width to substract from maxlength for /me padding
+#
+# /set neat_history <number>
+# * number : number of formatted lines to remember for dynamic mode
+#
+
+my @action_protos = qw(irc silc xmpp);
+my (%histories, %S, @style, @astyle, %format_ok, %cmmap);
+
+my $align_expando = '';
+my $trunc_expando = '';
+my $cumode_expando = '';
+
+my $format_re = qr/ %(?=[}%{])
+ | %[04261537kbgcrmywKBGCRMYWU9_8I:|FnN>#pP[]
+ | %[Zz][[:xdigit:]]{6}
+ | %[Xx](?i:0[a-f]|[1-6][0-9a-z]|7[a-x]) /x;
+
+sub update_expando {
+ my ($mode, $server, $target, $nick, $space) = @_;
+ my $t_add;
+ if (exists $Irssi::Script::{'realnames::'}
+ && (my $code = 'Irssi::Script::realnames'->can('_get_nick_chan'))) {
+ if (my $i = $code->($server, $target, $nick)) {
+ $nick = $i->{n}{realname}
+ if length $i->{n}{realname};
+ }
+ }
+ my $nl = length $nick;
+ my $pad_len = max(0, $space - $nl);
+ if ($S{truncate_nick}) {
+ if (($mode >= 4 && $S{trunc_in_anick})
+ || ($mode < 4 && $S{trunc_in_nick})) {
+ $t_add = $S{tnolen};
+ }
+ if ($nl + $t_add > $space) {
+ $trunc_expando = format_expand($S{tyes_char});
+ $t_add = $S{tyeslen} if defined $t_add;
+ }
+ else {
+ $trunc_expando = format_expand($S{tno_char});
+ }
+ $pad_len = max(0, $pad_len - $t_add) if $t_add;
+ }
+ else {
+ $trunc_expando = '';
+ }
+ if ($pad_len) {
+ my @subs = split /($format_re)/, $S{pad_char} x $pad_len;
+ $align_expando = '';
+ my $clen = 0;
+ while (@subs) {
+ my ($tx, $fmt) = splice @subs, 0, 2;
+ my $txlen = length $tx // 0;
+ $align_expando .= substr $tx, 0, ($pad_len - $clen) if defined $tx;
+ $clen += $txlen;
+ $align_expando .= $fmt if defined $fmt;
+ last if $clen >= $pad_len;
+ }
+ $align_expando = format_expand($align_expando.'%n');
+ }
+ else {
+ $align_expando = '';
+ }
+ return $t_add;
+}
+
+sub prnt_clear_levels {
+ my ($dest) = @_;
+ clear_ref() if $dest->{level}
+ & (MSGLEVEL_PUBLIC|MSGLEVEL_MSGS|MSGLEVEL_ACTIONS|MSGLEVEL_DCCMSGS|MSGLEVEL_NOTICES);
+}
+
+sub clear_ref {
+ $trunc_expando = $align_expando = $cumode_expando = '';
+}
+
+sub expando_nickalign { $align_expando }
+sub expando_nicktrunc { $trunc_expando }
+sub expando_nickcumode { $cumode_expando }
+
+Irssi::expando_create('nickalign', \&expando_nickalign, {
+ 'message public' => 'none',
+ 'message own_public' => 'none',
+ 'message private' => 'none',
+ 'message own_private' => 'none',
+ (map { ("message $_ action" => 'none',
+ "message $_ own_action" => 'none')
+ } @action_protos),
+ });
+Irssi::expando_create('nicktrunc', \&expando_nicktrunc, {
+ 'message public' => 'none',
+ 'message own_public' => 'none',
+ 'message private' => 'none',
+ 'message own_private' => 'none',
+ (map { ("message $_ action" => 'none',
+ "message $_ own_action" => 'none')
+ } @action_protos),
+ });
+Irssi::expando_create('nickcumode', \&expando_nickcumode, {
+ 'message public' => 'none',
+ 'message own_public' => 'none',
+ 'message private' => 'none',
+ 'message own_private' => 'none',
+ (map { ("message $_ action" => 'none',
+ "message $_ own_action" => 'none')
+ } @action_protos),
+ });
+
+sub init_hist {
+ my ($server, $target) = @_;
+ if (my $ch = $server->channel_find($target)) {
+ [ max map { length } map { $_->{nick} } $ch->nicks ]
+ }
+ else {
+ [ max map { length } $server->{nick}, $target ]
+ }
+}
+
+my %em = (
+ p => '$nickalign',
+ c => '$nickcolor',
+ t => '$nicktrunc',
+ m => '$nickcumode',
+ );
+
+my %formats = (
+ own_action => [5, '{ownaction ', '$0','}','$1' ],
+ action_public => [4, '{pubaction ', '$0','}','$1' ],
+ action_private => [4, '{pvtaction ', '$0','}','$2' ],
+ action_private_query => [4, '{pvtaction_query ','$0','}','$2' ],
+ # * * * # * *
+
+ own_msg_private_query => [3, '{ownprivmsgnick ', '' ,'{ownprivnick ','$2','}','' ,'}','$1' ],
+ msg_private_query => [2, '{privmsgnick ' ,'' ,'' ,'$0','' ,'' ,'}','$2' ],
+ own_msg => [1, '{ownmsgnick ' ,'$2',' {ownnick ' ,'$0','}','' ,'}','$1' ],
+ own_msg_channel => [1, '{ownmsgnick ' ,'$3',' {ownnick ' ,'$0','}','{msgchannel $1}','}','$2' ],
+ pubmsg_me => [0, '{pubmsgmenick ' ,'$2',' {menick ' ,'$0','}','' ,'}','$1' ],
+ pubmsg_me_channel => [0, '{pubmsgmenick ' ,'$3',' {menick ' ,'$0','}','{msgchannel $1}','}','$2' ],
+ pubmsg_hilight => [0, '{pubmsghinick $0 ','$3',' ' ,'$1', '','', ,'}','$2' ],
+ pubmsg_hilight_channel => [0, '{pubmsghinick $0 ','$4',' ' ,'$1', '','{msgchannel $2}','}','$3' ],
+ pubmsg => [0, '{pubmsgnick ' ,'$2',' {pubnick ' ,'$0','}','' ,'}','$1' ],
+ pubmsg_channel => [0, '{pubmsgnick ' ,'$3',' {pubnick ' ,'$0','}','{msgchannel $1}','}','$2' ],
+ # * * * * * # * * * *
+ );
+
+sub reformat_format {
+ Irssi::signal_remove('command format', 'update_formats');
+ Irssi::signal_remove('theme changed' => 'update_formats');
+ %format_ok = () unless @_;
+ my ($mode, $server, $target, $nick, $size) = @_;
+ for my $fmt (keys %formats) {
+ next if defined $mode && $formats{$fmt}[0] != $mode;
+
+ my @fs = @{ $formats{$fmt} };
+
+ my $ls;
+ if (defined $mode) {
+ $ls = $size;
+ }
+ else {
+ $ls = $fs[0] < 4 ? $S{max} : max(0, $S{max} - $S{melength});
+ }
+ next if exists $format_ok{$fmt} && $format_ok{$fmt} == $ls;
+
+ if ($S{truncate_nick} && $ls) {
+ $fs[ $fs[0] < 4 ? 4 : 2 ] =~ s/\$/\$[.$ls]/;
+ }
+ if ($S{custom_modes} && $fs[0] < 4) {
+ $fs[2] =~ s/\$\K\d/nickcumode/;
+ }
+ my $s;
+ local $em{c} = ''
+ if ($fs[1] =~ /menick/ && !$S{color_menick})
+ || ($fs[1] =~ /hinick/ && !$S{color_hinick});
+ my $sr = $fs[0] >= 4 ? \@astyle : \@style;
+ for my $i (1..$#fs) {
+ $s .= ($sr->[$i] =~ s/(.)/$em{$1}/gr) if defined $sr->[$i];
+ $s .= $fs[$i];
+ }
+ Irssi::command("^format $fmt $s");
+ $format_ok{$fmt} = $ls;
+ }
+ Irssi::signal_add_last({
+ 'theme changed' => 'update_formats',
+ 'command format' => 'update_formats',
+ });
+}
+
+sub update_nm {
+ my ($mode, $server, $target, $nick) = @_;
+ my $tg = $server->{tag};
+ if (my $ch = $server->channel_find($target)) {
+ $target = $ch->{name};
+ my $nickobj = $ch->nick_find($nick);
+ if ($nickobj) {
+ $nick = $nickobj->{nick};
+ my $mode = substr $nickobj->{prefixes}.' ', 0, 1;
+ $cumode_expando = exists $cmmap{$mode} ? format_expand($cmmap{$mode}) : $mode;
+ }
+ else {
+ $cumode_expando = '';
+ }
+ }
+ elsif (my $q = $server->query_find($target)) {
+ $target = $q->{name};
+ }
+
+ my $longest;
+ if ($S{dynamic}) {
+ my $hist = $histories{"$tg/$target"} ||= init_hist($server, $target);
+ my $last = $histories{"$tg/$target/last"} || 1;
+ unshift @$hist, length $nick;
+ if (@$hist > 2*$S{history}) {
+ splice @$hist, $S{history};
+ }
+ my @add;
+ unless ($S{shrink}) {
+ push @add, $last;
+ }
+ if ($S{staircase}) {
+ push @add, $last - 1
+ }
+ $longest = $histories{"$tg/$target/last"} = max(@$hist, @add);
+
+ if ($S{max} && ($S{max} < $longest || !$S{shrink})) {
+ $longest = $S{max};
+ }
+ }
+ else {
+ $longest = $S{max};
+ }
+
+ my $size = $mode < 4 ? $longest : max(0, $longest - $S{melength});
+ my $t_add = update_expando($mode, $server, $target, $nick, $size);
+ $size = max(0, $size - $t_add) if defined $t_add;
+ if ($S{dynamic}) {
+ reformat_format($mode, $server, $target, $nick, $size);
+ }
+}
+
+sub sig_setup {
+ my %old_S = %S;
+ $S{history} = Irssi::settings_get_int('neat_history');
+ $S{max} = Irssi::settings_get_int('neat_maxlength');
+ $S{melength} = Irssi::settings_get_int('neat_melength');
+
+ $S{dynamic} = Irssi::settings_get_bool('neat_dynamic');
+ $S{shrink} = Irssi::settings_get_bool('neat_shrink');
+ $S{staircase} = Irssi::settings_get_bool('neat_staircase_shrink');
+
+ $S{color_hinick} = Irssi::settings_get_bool('neat_color_hinick');
+ $S{color_menick} = Irssi::settings_get_bool('neat_color_menick');
+ $S{truncate_nick} = Irssi::settings_get_bool('neat_truncate_nick');
+ $S{custom_modes} = Irssi::settings_get_bool('neat_custom_modes');
+
+ if (!defined $old_S{dynamic} || $old_S{dynamic} != $S{dynamic}) {
+ %histories = ();
+ reformat_format();
+ }
+ elsif ($old_S{max} != $S{max} || $old_S{melength} != $S{melength}
+ || $old_S{color_hinick} != $S{color_hinick} || $old_S{color_menick} != $S{color_menick}
+ || $old_S{truncate_nick} != $S{truncate_nick} || $old_S{custom_modes} != $S{custom_modes}) {
+ reformat_format();
+ }
+}
+
+sub update_formats {
+ my $was_style = "@style";
+ $S{style} = Irssi::current_theme->get_format(__PACKAGE__, 'neat_style');
+ my $was_action_style = "@astyle";
+ $S{action_style} = Irssi::current_theme->get_format(__PACKAGE__, 'neat_action_style');
+ $S{pad_char} = Irssi::current_theme->get_format(__PACKAGE__, 'neat_pad_char');
+ $S{tno_char} = Irssi::current_theme->get_format(__PACKAGE__, 'neat_notruncate_char');
+ $S{tnolen} = length($S{tno_char} =~ s/$format_re//gr);
+ $S{tyeslen} = length($S{tyes_char} =~ s/$format_re//gr);
+ $S{tyes_char} = Irssi::current_theme->get_format(__PACKAGE__, 'neat_truncate_char');
+ @style = map { y/pct//cd; $_ } split /,/, $S{style};
+ @astyle = map { y/pctm//cd; $_ } split /,/, $S{action_style};
+ $S{trunc_in_nick} = grep { /t/ } @style[2..min($#style, 6)];
+ $S{trunc_in_anick} = grep { /t/ } @astyle[2..min($#astyle, 3)];
+ my $custom_modes = Irssi::current_theme->get_format(__PACKAGE__, 'neat_custom_modes');
+ %cmmap = map { (substr $_, 0, 1), (substr $_, 1) } $custom_modes =~ /(?:^\s?|\G\s?\|\s?)((?!\s\|)(?:[^\\|[:space:]]|\\.|\s(?!\||$))*)/sg;
+ if ($was_style ne "@style" || $was_action_style ne "@astyle") {
+ reformat_format();
+ }
+}
+
+{
+ my %format2control = (
+ 'F' => "\cDa", '_' => "\cDc", '|' => "\cDe", '#' => "\cDi", "n" => "\cDg", "N" => "\cDg",
+ 'U' => "\c_", '8' => "\cV", 'I' => "\cDf",
+ );
+ my %bg_base = (
+ '0' => '0', '4' => '1', '2' => '2', '6' => '3', '1' => '4', '5' => '5', '3' => '6', '7' => '7',
+ 'x08' => '8', 'x09' => '9', 'x0a' => ':', 'x0b' => ';', 'x0c' => '<', 'x0d' => '=', 'x0e' => '>', 'x0f' => '?',
+ );
+ my %fg_base = (
+ 'k' => '0', 'b' => '1', 'g' => '2', 'c' => '3', 'r' => '4', 'm' => '5', 'p' => '5', 'y' => '6', 'w' => '7',
+ 'K' => '8', 'B' => '9', 'G' => ':', 'C' => ';', 'R' => '<', 'M' => '=', 'P' => '=', 'Y' => '>', 'W' => '?',
+ );
+ my @ext_colour_off = (
+ '.', '-', ',',
+ '+', "'", '&',
+ );
+ sub format_expand {
+ $_[0] =~ s{%(Z.{6}|z.{6}|X..|x..|.)}{
+ my $c = $1;
+ if (exists $format2control{$c}) {
+ $format2control{$c}
+ }
+ elsif (exists $bg_base{$c}) {
+ "\cD/$bg_base{$c}"
+ }
+ elsif (exists $fg_base{$c}) {
+ "\cD$fg_base{$c}/"
+ }
+ elsif ($c =~ /^[{}%]$/) {
+ $c
+ }
+ elsif ($c =~ /^(z|Z)([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})$/) {
+ my $bg = $1 eq 'z';
+ my (@rgb) = map { hex $_ } $2, $3, $4;
+ my $x = $bg ? 0x1 : 0;
+ my $out = "\cD" . (chr -13 + ord '0');
+ for (my $i = 0; $i < 3; ++$i) {
+ if ($rgb[$i] > 0x20) {
+ $out .= chr $rgb[$i];
+ }
+ else {
+ $x |= 0x10 << $i; $out .= chr 0x20 + $rgb[$i];
+ }
+ }
+ $out .= chr 0x20 + $x;
+ $out
+ }
+ elsif ($c =~ /^(x)(?:0([[:xdigit:]])|([1-6])(?:([0-9])|([a-z]))|7([a-x]))$/i) {
+ my $bg = $1 eq 'x';
+ my $col = defined $2 ? hex $2
+ : defined $6 ? 232 + (ord lc $6) - (ord 'a')
+ : 16 + 36 * ($3 - 1) + (defined $4 ? $4 : 10 + (ord lc $5) - (ord 'a'));
+ if ($col < 0x10) {
+ my $chr = chr $col + ord '0';
+ "\cD" . ($bg ? "/$chr" : "$chr/")
+ }
+ else {
+ "\cD" . $ext_colour_off[($col - 0x10) / 0x50 + $bg * 3] . chr (($col - 0x10) % 0x50 - 1 + ord '0')
+ }
+ }
+ else {
+ "%$c"
+ }
+ }ger;
+ }
+}
+
+sub init {
+ update_formats();
+ sig_setup();
+ lock_keys(%S);
+ print "nm2 experimental version, please report issues. thanks!"
+}
+
+Irssi::settings_add_bool('misc', 'neat_dynamic', 1);
+Irssi::settings_add_bool('misc', 'neat_shrink', 1);
+Irssi::settings_add_bool('misc', 'neat_staircase_shrink', 0);
+
+Irssi::settings_add_bool('misc', 'neat_color_hinick', 0);
+Irssi::settings_add_bool('misc', 'neat_color_menick', 0);
+Irssi::settings_add_bool('misc', 'neat_truncate_nick', 1);
+Irssi::settings_add_bool('misc', 'neat_custom_modes', 0);
+
+Irssi::settings_add_int('misc', 'neat_maxlength', 0);
+Irssi::settings_add_int('misc', 'neat_melength', 2);
+Irssi::settings_add_int('misc', 'neat_history', 50);
+
+Irssi::signal_add('setup changed' => 'sig_setup');
+Irssi::signal_add_last({
+ 'setup reread' => 'sig_setup',
+ 'theme changed' => 'update_formats',
+ 'command format' => 'update_formats',
+ });
+
+Irssi::theme_register([
+ 'neat_style' => ' , , p , , c , t , , , ',
+ 'neat_action_style' => ' , p , , t , ',
+ 'neat_pad_char' => '%K.',
+ 'neat_truncate_char' => '%m+',
+ 'neat_notruncate_char' => '',
+ 'neat_custom_modes' => '&%B&%n | @%g@%n | +%y+%n',
+ ]);
+
+Irssi::signal_add_first({
+ 'message public' => sub {
+ my ($server, $msg, $nick, $address, $target) = @_;
+ update_nm(0, $server, $target, $nick);
+ },
+ 'message private' => sub {
+ my ($server, $msg, $nick, $address) = @_;
+ update_nm(2, $server, $nick, $nick);
+ },
+ (map { ("message $_ action" => sub {
+ my ($server, $msg, $nick, $address, $target) = @_;
+ update_nm(4, $server, $target, $nick);
+ }) } qw(irc silc)),
+ 'message xmpp action' => sub {
+ return unless @_;
+ my ($server, $msg, $nick, $target) = @_;
+ update_nm(4, $server, $target, $nick);
+ },
+ });
+
+sub channel_nick {
+ my ($server, $target) = @_;
+ ($server->channel_find($target)||+{ownnick=>$server})->{ownnick}{nick}
+}
+
+Irssi::signal_add_first({
+ 'message own_public' => sub {
+ my ($server, $msg, $target) = @_;
+ update_nm(1, $server, $target, channel_nick($server, $target));
+ },
+ 'message own_private' => sub {
+ my ($server, $msg, $target) = @_;
+ update_nm(3, $server, $target, $server->{nick});
+ },
+ (map { ("message $_ own_action" => sub {
+ my ($server, $msg, $target) = @_;
+ update_nm(5, $server, $target, $server->{nick});
+ }) } qw(irc silc)),
+ 'message xmpp own_action' => sub {
+ return unless @_;
+ my ($server, $msg, $target) = @_;
+ update_nm(5, $server, $target, channel_nick($server, $target));
+ },
+ });
+Irssi::signal_add_last({
+ 'channel destroyed' => sub {
+ my ($channel) = @_;
+ delete $histories{ $channel->{server}{tag} . '/' . $channel->{name} };
+ delete $histories{ $channel->{server}{tag} . '/' . $channel->{name} . '/last' };
+ },
+ 'query destroyed' => sub {
+ my ($query) = @_;
+ delete $histories{ $query->{server}{tag} . '/' . $query->{name} };
+ delete $histories{ $query->{server}{tag} . '/' . $query->{name} . '/last' };
+ },
+ 'query nick changed' => sub {
+ my ($query, $old_nick) = @_;
+ delete $histories{ $query->{server}{tag} . '/' . $old_nick };
+ delete $histories{ $query->{server}{tag} . '/' . $old_nick . '/last' };
+ },
+ 'query server changed' => sub {
+ my ($query, $old_server) = @_;
+ delete $histories{ $old_server->{tag} . '/' . $query->{name} };
+ delete $histories{ $old_server->{tag} . '/' . $query->{name} . '/last' };
+ }
+ });
+Irssi::signal_add({
+ 'print text' => 'prnt_clear_levels',
+});
+
+init();
+
+# Changelog
+# =========
+# 2.1 - support realnames script
+#
+# 2.0
+# - fix crash if xmpp action signal is not registered (just ignore it)
+# - do not grow either when using no-shrink with maxlength
+# - hopefully fix alignment in xmpp muc
diff --git a/.irssi/scripts/tmux-nicklist-portable.pl b/.irssi/scripts/tmux-nicklist-portable.pl
new file mode 100644
index 0000000..e0c6920
--- /dev/null
+++ b/.irssi/scripts/tmux-nicklist-portable.pl
@@ -0,0 +1,432 @@
+# based on the nicklist.pl script
+################################################################################
+# tmux_nicklist.pl
+# This script integrates tmux and irssi to display a list of nicks in a
+# vertical right pane with 20% width. Right now theres no configuration
+# or setup, simply initialize the script with irssi and by default you
+# will get the nicklist for every channel(customize by altering
+# the regex in /set nicklist_channel_re)
+#
+# /set nicklist_channel_re <regex>
+# * only show on channels matching this regular expression
+#
+# /set nicklist_max_users <num>
+# * only show when the channel has so many users or less (0 = always)
+#
+# /set nicklist_smallest_main <num>
+# * only show when main window is larger than this (0 = always)
+#
+# /set nicklist_pane_width <num>
+# * width of the nicklist pane
+#
+# /set nicklist_color <ON|OFF>
+# * colourise the nicks in the nicklist (required nickcolor script
+# with get_nick_color2 and debug_ansicolour functions)
+#
+# /set nicklist_gone_sort <ON|OFF>
+# * sort away people below
+#
+# It supports mouse scrolling and the following keys:
+# k/up arrow: up one line
+# j/down arrow: down one line
+# u/pageup: up 50% lines
+# d/pagedown: down 50% lines
+# gg: go to top
+# G: go to bottom
+#
+# For better integration, unrecognized sequences will be sent to irssi and
+# its pane will be focused.
+#
+# to toggle the nicklist if it is in the way you can make a key binding:
+# /bind meta-Z /script exec Irssi::Script::tmux_nicklist_portable::toggle_nicklist
+################################################################################
+
+use strict;
+use warnings;
+use IO::Handle;
+use IO::Select;
+use POSIX;
+use File::Temp qw/ :mktemp /;
+use File::Basename;
+our $VERSION = '0.1.8';
+our %IRSSI = (
+ authors => 'Thiago de Arruda',
+ contact => 'tpadilha84@gmail.com',
+ name => 'tmux-nicklist',
+ description => 'displays a list of nicks in a separate tmux pane',
+ license => 'WTFPL',
+);
+
+# "other" prefixes by danielg4 <daniel@gimpelevich.san-francisco.ca.us>
+# added 'd' and 'u' navigation as in vim, by @gerardbm (github)
+
+{ package Irssi::Nick }
+
+if ($#ARGV == -1) {
+require Irssi;
+
+my $enabled = 0;
+my $nicklist_toggle = 1;
+my $script_path = __FILE__;
+my $tmpdir;
+my $fifo_path;
+my $fifo;
+my $just_launched;
+my $resize_timer;
+
+sub enable_nicklist {
+ return if ($enabled);
+ $tmpdir = mkdtemp Irssi::get_irssi_dir()."/nicklist-XXXXXXXX";
+ $fifo_path = "$tmpdir/fifo";
+ POSIX::mkfifo($fifo_path, 0600) or die "can't mkfifo $fifo_path: $!";
+ my $cmd = "perl $script_path $fifo_path $ENV{TMUX_PANE}";
+ my $width = Irssi::settings_get_int('nicklist_pane_width');
+ system('tmux', 'split-window', '-dh', '-l', $width, '-t', $ENV{TMUX_PANE}, $cmd);
+ open_fifo();
+ Irssi::timeout_remove($just_launched) if defined $just_launched;
+ $just_launched = Irssi::timeout_add_once(300, sub { $just_launched = undef; }, '');
+}
+
+sub open_fifo {
+ # The next system call will block until the other pane has opened the pipe
+ # for reading, so synchronization is not an issue here.
+ open $fifo, ">", $fifo_path or do {
+ if ($! == 4) {
+ Irssi::timeout_add_once(300, \&open_fifo, '');
+ $enabled = -1 unless $enabled;
+ return;
+ }
+ die "can't open $fifo_path: $!";
+ };
+ $fifo->autoflush(1);
+ if ($enabled < -1) {
+ $enabled = 1;
+ disable_nicklist();
+ } elsif ($enabled == -1) {
+ $enabled = 1;
+ reset_nicklist("enabled");
+ } else {
+ $enabled = 1;
+ }
+}
+
+sub disable_nicklist {
+ return unless ($enabled);
+ if ($enabled > 0) {
+ print $fifo "EXIT\n";
+ close $fifo;
+ $fifo = undef;
+ unlink $fifo_path;
+ rmdir $tmpdir;
+ }
+ $enabled--;
+}
+
+sub reset_nicklist {
+ my $event = shift;
+ my $active = Irssi::active_win();
+ my $channel = $active->{active};
+ return disable_nicklist unless $channel && ref $channel;
+ if ($event =~ /^nick/) {
+ # check if that nick event is for the current channel/nicklist
+ my ($event_channel) = @_;
+ return unless $channel->{_irssi} == $event_channel->{_irssi};
+ }
+ my ($colourer, $ansifier);
+ if (Irssi::settings_get_bool('nicklist_color')) {
+ for my $script (sort map { my $z = $_; $z =~ s/::$//; $z } grep { /^nickcolor|nm/ } keys %Irssi::Script::) {
+ if ($colourer = "Irssi::Script::$script"->can('get_nick_color2')) {
+ $ansifier = "Irssi::Script::$script"->can('debug_ansicolour');
+ last;
+ }
+ }
+ }
+ my $channel_pattern = Irssi::settings_get_str('nicklist_channel_re');
+ { local $@;
+ $channel_pattern = eval { qr/$channel_pattern/ };
+ $channel_pattern = qr/(?!)/ if $@;
+ }
+ my $smallest_main = Irssi::settings_get_int('nicklist_smallest_main');
+ if (!$nicklist_toggle
+ || !$channel || !ref($channel)
+ || !$channel->isa('Irssi::Channel')
+ || !$channel->{'names_got'}
+ || $channel->{'name'} !~ $channel_pattern
+ || ($smallest_main && $channel->window->{width} < $smallest_main)) {
+ disable_nicklist;
+ } else {
+ my %colour;
+ my @nicks = $channel->nicks();
+ my $max_nicks = Irssi::settings_get_int('nicklist_max_users');
+ if ($max_nicks && @nicks > $max_nicks) {
+ disable_nicklist;
+ } else {
+ enable_nicklist;
+ return unless $enabled > 0;
+ foreach my $nick (sort { $a->{_irssi} <=> $b->{_irssi} } @nicks) {
+ $colour{$nick->{nick}} = ($ansifier && $colourer) ? $ansifier->($colourer->($active->{active}{server}{tag}, $channel->{name}, $nick->{nick}, 0)) : '';
+ }
+ print($fifo "BEGIN\n");
+ my $gone_sort = Irssi::settings_get_bool('nicklist_gone_sort');
+ my $prefer_real;
+ if (exists $Irssi::Script::{'realnames::'}) {
+ my $code = "Irssi::Script::realnames"->can('use_realnames');
+ $prefer_real = $code && $code->($channel);
+ }
+ my $_real = sub {
+ my $nick = shift;
+ $prefer_real && length $nick->{'realname'} ? $nick->{'realname'} : $nick->{'nick'}
+ };
+ foreach my $nick (sort {($a->{'op'}?'1':$a->{'halfop'}?'2':$a->{'voice'}?'3':$a->{'other'}>32?'0':'4').($gone_sort?($a->{'gone'}?1:0):'').lc($_real->($a))
+ cmp ($b->{'op'}?'1':$b->{'halfop'}?'2':$b->{'voice'}?'3':$b->{'other'}>32?'0':'4').($gone_sort?($b->{'gone'}?1:0):'').lc($_real->($b))} @nicks) {
+ my $colour = $colour{$nick->{nick}} || "\e[39m";
+ $colour = "\e[37m" if $nick->{'gone'};
+ print($fifo "NICK");
+ if ($nick->{'op'}) {
+ print($fifo "\e[32m\@$colour".$_real->($nick)."\e[39m");
+ } elsif ($nick->{'halfop'}) {
+ print($fifo "\e[34m%$colour".$_real->($nick)."\e[39m");
+ } elsif ($nick->{'voice'}) {
+ print($fifo "\e[33m+$colour".$_real->($nick)."\e[39m");
+ } elsif ($nick->{'other'}>32) {
+ print($fifo "\e[31m".(chr $nick->{'other'})."$colour".$_real->($nick)."\e[39m");
+ } else {
+ print($fifo " $colour".$_real->($nick)."\e[39m");
+ }
+ print($fifo "\n");
+ }
+ print($fifo "END\n");
+ }
+ }
+}
+
+sub toggle_nicklist {
+ if ($enabled) {
+ $nicklist_toggle = undef
+ } else {
+ $nicklist_toggle = 1;
+ }
+ reset_nicklist("toggle");
+}
+
+sub switch_channel {
+ print $fifo "SWITCH_CHANNEL\n" if $fifo;
+ &reset_nicklist;
+}
+
+sub resized_timed {
+ Irssi::timeout_remove($resize_timer) if defined $resize_timer;
+ return if defined $just_launched;
+ $resize_timer = Irssi::timeout_add_once(1100, \&resized, '');
+ #resized();
+}
+sub resized {
+ $resize_timer = undef;
+ return if defined $just_launched;
+ return unless $enabled >= 0;
+ disable_nicklist;
+ Irssi::timeout_add_once(200, sub{reset_nicklist("terminal resized")}, '');
+}
+sub UNLOAD {
+ disable_nicklist;
+}
+
+Irssi::settings_add_str('tmux_nicklist', 'nicklist_channel_re', '.*');
+Irssi::settings_add_int('tmux_nicklist', 'nicklist_max_users', 0);
+Irssi::settings_add_int('tmux_nicklist', 'nicklist_smallest_main', 0);
+Irssi::settings_add_int('tmux_nicklist', 'nicklist_pane_width', 13);
+Irssi::settings_add_bool('tmux_nicklist', 'nicklist_color', 1);
+Irssi::settings_add_bool('tmux_nicklist', 'nicklist_gone_sort', 0);
+Irssi::signal_add_last('window item changed', sub{switch_channel("window item changed",@_)});
+Irssi::signal_add_last('window changed', sub{switch_channel("window changed",@_)});
+Irssi::signal_add_last('channel joined', sub{switch_channel("channel joined",@_)});
+Irssi::signal_add('nicklist new', sub{reset_nicklist("nicklist new",@_)});
+Irssi::signal_add('nicklist remove', sub{reset_nicklist("nicklist remove",@_)});
+Irssi::signal_add('nicklist changed', sub{reset_nicklist("nicklist changed",@_)});
+Irssi::signal_add_first('nick mode changed', sub{reset_nicklist("nick mode changed",@_)});
+Irssi::signal_add('gui exit', \&disable_nicklist);
+Irssi::signal_add_last('terminal resized', \&resized_timed);
+
+} else {
+my $fifo_path = $ARGV[0];
+my $irssi_pane = $ARGV[1];
+# array to store the current channel nicknames
+my @nicknames = ();
+
+# helper functions for manipulating the terminal
+# escape sequences taken from
+# http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
+sub enable_mouse { print "\e[?1000h"; }
+# recognized sequences
+my $MOUSE_SCROLL_DOWN="\e[Ma";
+my $MOUSE_SCROLL_UP="\e[M`";
+my $ARROW_DOWN="\e[B";
+my $ARROW_UP="\e[A";
+my $DOWN="j";
+my $UP="k";
+my $PAGE_DOWN="\e[6~";
+my $PAGE_UP="\e[5~";
+my $PAGE_DOWN_D="d";
+my $PAGE_UP_U="u";
+my $GO_TOP="gg";
+my $GO_BOTTOM="G";
+
+my $current_line = 0;
+my $sequence = '';
+my ($rows, $cols);
+
+sub term_size {
+ split ' ', `stty size`;
+}
+
+sub redraw {
+ my $last_nick_idx = @nicknames;
+ my $last_idx = $current_line + $rows;
+ # normalize last visible index
+ if ($last_idx > ($last_nick_idx)) {
+ $last_idx = $last_nick_idx;
+ }
+ # redraw visible nicks
+ for my $i (reverse 1..$rows) {
+ print "\e[$i;1H\e[K";
+ my $idx = $current_line + $i - 1;
+ if ($idx < $last_idx) {
+ my $z = 0; my $col = $cols;
+ for (split /(\e\[(?:\d|;|:|\?|\s)*.)/, $nicknames[$idx]) {
+ if ($z ^= 1) {
+ print +(substr $_, 0, $col) if $col > 0;
+ $col -= length;
+ } else {
+ print
+ }
+ }
+ }
+ }
+}
+
+sub move_down {
+ $sequence = '';
+ my $count = int $_[0];
+ my $nickcount = $#nicknames;
+ return if ($nickcount <= $rows);
+ if ($count == -1) {
+ $current_line = $nickcount - $rows + 1;
+ redraw;
+ return;
+ }
+ my $visible = $nickcount - $current_line - $count + 1;
+ if ($visible > $rows) {
+ $current_line += $count;
+ redraw;
+ } elsif (($visible + $count) > $rows) {
+ # scroll the maximum we can
+ $current_line = $nickcount - $rows + 1;
+ redraw;
+ }
+}
+
+sub move_up {
+ $sequence = '';
+ my $count = int $_[0];
+ if ($count == -1) {
+ $current_line = 0;
+ redraw;
+ return;
+ }
+ return if ($current_line == 0);
+ $count = 1 if $count == 0;
+ $current_line -= $count;
+ $current_line = 0 if $current_line < 0;
+ redraw;
+}
+
+$SIG{INT} = 'IGNORE';
+
+STDOUT->autoflush(1);
+# setup terminal so we can listen for individual key presses without echo
+`stty -icanon -echo`;
+
+# open named pipe and setup the 'select' wrapper object for listening on both
+# fds(fifo and sdtin)
+open my $fifo, "<", $fifo_path or die "can't open $fifo_path: $!";
+my $select = IO::Select->new();
+my @ready;
+$select->add($fifo);
+$select->add(\*STDIN);
+
+enable_mouse;
+system('tput', 'smcup');
+print "\e[?7l"; #system('tput', 'rmam');
+system('tput', 'civis');
+MAIN: {
+ while (@ready = $select->can_read) {
+ foreach my $fd (@ready) {
+ ($rows, $cols) = term_size;
+ if ($fd == $fifo) {
+ while (<$fifo>) {
+ my $line = $_;
+ if ($line =~ /^BEGIN/) {
+ @nicknames = ();
+ } elsif ($line =~ /^SWITCH_CHANNEL/) {
+ $current_line = 0;
+ } elsif ($line =~ /^NICK(.+)$/) {
+ push @nicknames, $1;
+ } elsif ($line =~ /^END$/) {
+ redraw;
+ last;
+ } elsif ($line =~ /^EXIT$/) {
+ last MAIN;
+ }
+ }
+ } else {
+ my $key = '';
+ sysread(STDIN, $key, 1);
+ $sequence .= $key;
+ if ($MOUSE_SCROLL_DOWN =~ /^\Q$sequence\E/) {
+ if ($MOUSE_SCROLL_DOWN eq $sequence) {
+ move_down 3;
+ # mouse scroll has two more bytes that I dont use here
+ # so consume them now to avoid sending unwanted bytes to
+ # irssi
+ sysread(STDIN, $key, 2);
+ }
+ } elsif ($MOUSE_SCROLL_UP =~ /^\Q$sequence\E/) {
+ if ($MOUSE_SCROLL_UP eq $sequence) {
+ move_up 3;
+ sysread(STDIN, $key, 2);
+ }
+ } elsif ($ARROW_DOWN =~ /^\Q$sequence\E/) {
+ move_down 1 if ($ARROW_DOWN eq $sequence);
+ } elsif ($ARROW_UP =~ /^\Q$sequence\E/) {
+ move_up 1 if ($ARROW_UP eq $sequence);
+ } elsif ($DOWN =~ /^\Q$sequence\E/) {
+ move_down 1 if ($DOWN eq $sequence);
+ } elsif ($UP =~ /^\Q$sequence\E/) {
+ move_up 1 if ($UP eq $sequence);
+ } elsif ($PAGE_DOWN =~ /^\Q$sequence\E/) {
+ move_down $rows/2 if ($PAGE_DOWN eq $sequence);
+ } elsif ($PAGE_UP =~ /^\Q$sequence\E/) {
+ move_up $rows/2 if ($PAGE_UP eq $sequence);
+ } elsif ($PAGE_DOWN_D =~ /^\Q$sequence\E/) {
+ move_down $rows/2 if ($PAGE_DOWN_D eq $sequence);
+ } elsif ($PAGE_UP_U =~ /^\Q$sequence\E/) {
+ move_up $rows/2 if ($PAGE_UP_U eq $sequence);
+ } elsif ($GO_BOTTOM =~ /^\Q$sequence\E/) {
+ move_down -1 if ($GO_BOTTOM eq $sequence);
+ } elsif ($GO_TOP =~ /^\Q$sequence\E/) {
+ move_up -1 if ($GO_TOP eq $sequence);
+ } else {
+ # Unrecognized sequences will be send to irssi and its pane
+ # will be focused
+ system('tmux', 'send-keys', '-t', $irssi_pane, $sequence);
+ system('tmux', 'select-pane', '-t', $irssi_pane);
+ $sequence = '';
+ }
+ }
+ }
+ }
+}
+
+close $fifo;
+
+}
diff --git a/.oh-my-zsh/custom/plugins/zsh-autocomplete b/.oh-my-zsh/custom/plugins/zsh-autocomplete
new file mode 160000
+Subproject 20f6c34f20270084b21211428afb6d2534aae8e
diff --git a/.oh-my-zsh/custom/plugins/zsh-autosuggestions b/.oh-my-zsh/custom/plugins/zsh-autosuggestions
new file mode 160000
+Subproject 85919cd1ffa7d2d5412f6d3fe437ebdbeeec4fc
diff --git a/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting b/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting
new file mode 160000
+Subproject 1d85c692615a25fe2293bdd44b34c217d5d2bf0
diff --git a/.tmux.conf b/.tmux.conf
new file mode 100644
index 0000000..aca9b74
--- /dev/null
+++ b/.tmux.conf
@@ -0,0 +1,22 @@
+set -g mouse on
+set -g default-terminal "screen-256color"
+set -g status-bg colour0
+set -g set-clipboard on
+set -g @mighty-scroll-interval 3
+set -g @mighty-scroll-by-line 'man fzf'
+set -g @mighty-scroll-select-pane off
+set-option -g status-position top
+set-option -g status-right-length 150
+
+# plugins
+set -g @plugin 'tmux-plugins/tpm'
+set -g @plugin 'tmux-plugins/tmux-sensible'
+set -g @plugin 'noscript/tmux-mighty-scroll'
+set -g @plugin 'tmux-plugins/tmux-resurrect'
+set -g @plugin 'tmux-plugins/tmux-continuum'
+set -g @plugin 'tmux-plugins/tmux-logging'
+set -g @plugin 'erikw/tmux-powerline'
+set-option -g @plugin 'b0o/tmux-autoreload'
+
+set-option -g @tmux-autoreload-configs '~/.tmux.conf'
+run '~/.tmux/plugins/tpm/tpm'
diff --git a/.tmux/plugins/tmux-autoreload b/.tmux/plugins/tmux-autoreload
new file mode 160000
+Subproject e98aa3b74cfd5f2df2be2b5d4aa4ddcc843b2eb
diff --git a/.tmux/plugins/tmux-continuum b/.tmux/plugins/tmux-continuum
new file mode 160000
+Subproject 0698e8f4b17d6454c71bf5212895ec055c578da
diff --git a/.tmux/plugins/tmux-logging b/.tmux/plugins/tmux-logging
new file mode 160000
+Subproject b5c5f7b9bc679ca161a442e932d6186da8d3538
diff --git a/.tmux/plugins/tmux-mighty-scroll b/.tmux/plugins/tmux-mighty-scroll
new file mode 160000
+Subproject fa5db0718e9e9f7278520ecf63b96b84b0cc57d
diff --git a/.tmux/plugins/tmux-powerline b/.tmux/plugins/tmux-powerline
new file mode 160000
+Subproject d70011158dc389070d6ed7a67b65367206b6dde
diff --git a/.tmux/plugins/tmux-resurrect b/.tmux/plugins/tmux-resurrect
new file mode 160000
+Subproject cff343cf9e81983d3da0c8562b01616f12e8d54
diff --git a/.tmux/plugins/tmux-sensible b/.tmux/plugins/tmux-sensible
new file mode 160000
+Subproject 25cb91f42d020f675bb0a2ce3fbd3a5d96119ef
diff --git a/.tmux/plugins/tpm b/.tmux/plugins/tpm
new file mode 160000
+Subproject 99469c4a9b1ccf77fade25842dc7bafbc8ce994
diff --git a/.zshrc b/.zshrc
new file mode 100644
index 0000000..17177db
--- /dev/null
+++ b/.zshrc
@@ -0,0 +1,117 @@
+# If you come from bash you might have to change your $PATH.
+# export PATH=$HOME/bin:/usr/local/bin:$PATH
+
+# Path to your oh-my-zsh installation.
+export ZSH="$HOME/.oh-my-zsh"
+
+# Set name of the theme to load --- if set to "random", it will
+# load a random theme each time oh-my-zsh is loaded, in which case,
+# to know which specific one was loaded, run: echo $RANDOM_THEME
+# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
+ZSH_THEME="agnoster"
+
+# Set list of themes to pick from when loading at random
+# Setting this variable when ZSH_THEME=random will cause zsh to load
+# a theme from this variable instead of looking in $ZSH/themes/
+# If set to an empty array, this variable will have no effect.
+# ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" )
+
+# Uncomment the following line to use case-sensitive completion.
+# CASE_SENSITIVE="true"
+
+# Uncomment the following line to use hyphen-insensitive completion.
+# Case-sensitive completion must be off. _ and - will be interchangeable.
+# HYPHEN_INSENSITIVE="true"
+
+# Uncomment one of the following lines to change the auto-update behavior
+# zstyle ':omz:update' mode disabled # disable automatic updates
+# zstyle ':omz:update' mode auto # update automatically without asking
+# zstyle ':omz:update' mode reminder # just remind me to update when it's time
+
+# Uncomment the following line to change how often to auto-update (in days).
+# zstyle ':omz:update' frequency 13
+
+# Uncomment the following line if pasting URLs and other text is messed up.
+DISABLE_MAGIC_FUNCTIONS="true"
+
+# Uncomment the following line to disable colors in ls.
+# DISABLE_LS_COLORS="true"
+
+# Uncomment the following line to disable auto-setting terminal title.
+DISABLE_AUTO_TITLE="true"
+
+# Uncomment the following line to enable command auto-correction.
+# ENABLE_CORRECTION="true"
+
+# Uncomment the following line to display red dots whilst waiting for completion.
+# You can also set it to another string to have that shown instead of the default red dots.
+# e.g. COMPLETION_WAITING_DOTS="%F{yellow}waiting...%f"
+# Caution: this setting can cause issues with multiline prompts in zsh < 5.7.1 (see #5765)
+# COMPLETION_WAITING_DOTS="true"
+
+# Uncomment the following line if you want to disable marking untracked files
+# under VCS as dirty. This makes repository status check for large repositories
+# much, much faster.
+# DISABLE_UNTRACKED_FILES_DIRTY="true"
+
+# Uncomment the following line if you want to change the command execution time
+# stamp shown in the history command output.
+# You can set one of the optional three formats:
+# "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd"
+# or set a custom format using the strftime function format specifications,
+# see 'man strftime' for details.
+# HIST_STAMPS="mm/dd/yyyy"
+
+# Would you like to use another custom folder than $ZSH/custom?
+# ZSH_CUSTOM=/path/to/new-custom-folder
+
+# Which plugins would you like to load?
+# Standard plugins can be found in $ZSH/plugins/
+# Custom plugins may be added to $ZSH_CUSTOM/plugins/
+# Example format: plugins=(rails git textmate ruby lighthouse)
+# Add wisely, as too many plugins slow down shell startup.
+plugins=(git brew zsh-autosuggestions zsh-syntax-highlighting zsh-autocomplete colored-man-pages command-not-found safe-paste colorize taskwarrior)
+
+source $ZSH/oh-my-zsh.sh
+
+# User configuration
+
+# export MANPATH="/usr/local/man:$MANPATH"
+
+# You may need to manually set your language environment
+# export LANG=en_US.UTF-8
+
+# Preferred editor for local and remote sessions
+# if [[ -n $SSH_CONNECTION ]]; then
+# export EDITOR='vim'
+# else
+# export EDITOR='nvim'
+# fi
+
+# Compilation flags
+# export ARCHFLAGS="-arch x86_64"
+
+# Set personal aliases, overriding those provided by oh-my-zsh libs,
+# plugins, and themes. Aliases can be placed here, though oh-my-zsh
+# users are encouraged to define aliases within the ZSH_CUSTOM folder.
+# For a full list of active aliases, run `alias`.
+#
+# Example aliases
+# alias zshconfig="mate ~/.zshrc"
+# alias ohmyzsh="mate ~/.oh-my-zsh"
+
+export PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$HOME/.local/bin
+
+alias vim="nvim"
+alias cat="ccat"
+
+prompt_context(){}
+export PATH="/opt/homebrew/sbin:$PATH"
+export JAVA_HOME="/opt/homebrew/opt/openjdk"
+export PATH="$JAVA_HOME/bin:$PATH"
+export PATH="$HOME/Library/Python/3.14/bin:$PATH"
+export HOMEBREW_NO_UPDATE_REPORT_NEW=1
+
+
+test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh" || true
+
diff --git a/Brewfile b/Brewfile
new file mode 100644
index 0000000..6d4ef56
--- /dev/null
+++ b/Brewfile
@@ -0,0 +1,130 @@
+brew "openssl@3"
+brew "tree"
+brew "ansible"
+brew "ansible-lint"
+brew "ansifilter"
+brew "calc"
+brew "tree-sitter"
+brew "cask"
+brew "chroma"
+brew "cpanminus"
+brew "docker"
+brew "dos2unix"
+brew "entr"
+brew "exif"
+brew "fd"
+brew "feh"
+brew "ffmpeg"
+brew "fzf"
+brew "yt-dlp"
+brew "gallery-dl"
+brew "openjpeg"
+brew "ghostscript"
+brew "git"
+brew "git-lfs"
+brew "go"
+brew "gobuster"
+brew "openjdk"
+brew "groovy"
+brew "handbrake", link: false
+brew "hashcat"
+brew "ncurses"
+brew "htop"
+brew "hydra"
+brew "imagemagick"
+brew "iperf3"
+brew "irssi"
+brew "john"
+brew "lazygit"
+brew "mas"
+brew "masscan"
+brew "mkvtoolnix"
+brew "mpv"
+brew "mupdf-tools"
+brew "ncdu"
+brew "neovim"
+brew "nikto"
+brew "nmap"
+brew "node"
+brew "pandoc"
+brew "perl"
+brew "powershell", link: false
+brew "pwncat"
+brew "python@3.12"
+brew "python@3.13"
+brew "rclone"
+brew "ripgrep"
+brew "ripgrep-all"
+brew "rsync"
+brew "rust"
+brew "sevenzip"
+brew "shellcheck"
+brew "shfmt"
+brew "task"
+brew "taskwarrior-tui"
+brew "testdisk"
+brew "theharvester"
+brew "tmux"
+brew "unum"
+brew "uv"
+brew "watch"
+brew "web-ext"
+brew "wget"
+brew "wireshark"
+brew "zsh"
+cask "angry-ip-scanner"
+cask "balenaetcher"
+cask "betterdisplay"
+cask "caffeine"
+cask "cursor"
+cask "db-browser-for-sqlite"
+cask "dbeaver-community"
+cask "docker-desktop"
+cask "drawio"
+cask "firefox"
+cask "font-hack-nerd-font"
+cask "gimp"
+cask "google-chrome"
+cask "handbrake-app"
+cask "hex-fiend"
+cask "iina"
+cask "iterm2"
+cask "jump-desktop"
+cask "libreoffice"
+cask "makemkv"
+cask "mediainfo"
+cask "obsidian"
+cask "openvpn-connect"
+cask "powershell"
+cask "rapidapi"
+cask "spotify"
+cask "stats"
+cask "sublime-text"
+mas "Apple Configurator", id: 1037126344
+mas "DaVinci Resolve", id: 571213070
+vscode "ahmadawais.shades-of-purple"
+vscode "davidanson.vscode-markdownlint"
+vscode "enkia.tokyo-night"
+vscode "foxundermoon.shell-format"
+vscode "gitlab.gitlab-workflow"
+vscode "kevinrose.vsc-python-indent"
+vscode "ms-python.debugpy"
+vscode "ms-python.python"
+vscode "ms-python.vscode-pylance"
+vscode "ms-python.vscode-python-envs"
+vscode "ms-toolsai.jupyter"
+vscode "ms-toolsai.jupyter-keymap"
+vscode "ms-toolsai.jupyter-renderers"
+vscode "ms-toolsai.vscode-jupyter-cell-tags"
+vscode "ms-toolsai.vscode-jupyter-slideshow"
+vscode "ms-vscode.live-server"
+vscode "ms-vscode.powershell"
+vscode "ms-vscode.remote-explorer"
+vscode "ms-vscode.remote-server"
+vscode "ms-vsliveshare.vsliveshare"
+vscode "redhat.ansible"
+vscode "redhat.vscode-xml"
+vscode "redhat.vscode-yaml"
+vscode "sidthesloth.html5-boilerplate"
+vscode "yzhang.markdown-all-in-one"
+uv "ansible-dev-environment"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f043054
--- /dev/null
+++ b/README.md
@@ -0,0 +1,36 @@
+# Mac Dotfiles
+
+Dotfiles for MacOS
+
+## Installation
+
+```bash
+chmod +x ./scripts/*.sh
+./scripts/setup-mac.sh
+./scripts/omz.sh
+./scripts/brew.sh
+mkdir -p ~/.tmux/plugins
+git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
+cp .tmux.conf ~/.tmux.conf
+~/.tmux/plugins/tpm/bin/install_plugins
+```
+
+## MacOS System Preferences (setup-mac.sh)
+
+- Dock on the left with autohide
+- Screenshots save to Downloads folder
+- Hidden desktop items
+- Finder with path bar and folder then file A-Z sorting
+- Fast keyboard repeat
+
+## Dynamic iTerm2 colours depending on wallpaper via wal-item.py script
+
+```bash
+cd iTerm
+python3 -m venv .venv
+source .venv/bin/activate
+python3 -m pip install pywal16 haishoku
+python3 wal-iterm.py ~/path/to/wallpaper.png
+```
+
+If you dont see any change make sure your default profile is set to wal
diff --git a/iTerm/DynamicProfiles/wal-profile.json b/iTerm/DynamicProfiles/wal-profile.json
new file mode 100644
index 0000000..6f625aa
--- /dev/null
+++ b/iTerm/DynamicProfiles/wal-profile.json
@@ -0,0 +1,10 @@
+{
+ "Profiles" : [
+ {
+ "Use Separate Colors for Light and Dark Mode" : false,
+ "Name" : "wal",
+ "Rewritable" : true,
+ "Guid" : "wal-dynamic-profile-uuid"
+ }
+ ]
+} \ No newline at end of file
diff --git a/iTerm/wal-iterm.py b/iTerm/wal-iterm.py
new file mode 100644
index 0000000..6e9b443
--- /dev/null
+++ b/iTerm/wal-iterm.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+"""
+Script to run pywal and apply colors to iTerm2 automatically.
+Usage: python3 wal-iterm.py [path_to_image]
+"""
+
+import subprocess
+import sys
+import os
+import json
+import tempfile
+from pathlib import Path
+import plistlib
+
+HOME = Path.home()
+WAL_CACHE = HOME / ".cache" / "wal"
+ITERM_COLORS_DIR = WAL_CACHE / "itermcolors"
+COLORS_JSON = WAL_CACHE / "colors.json"
+
+
+def run_command(cmd, check=True):
+ """Run a shell command and return the result."""
+ try:
+ result = subprocess.run(
+ cmd, shell=True, capture_output=True, text=True, check=check
+ )
+ return result.stdout.strip(), result.stderr.strip(), result.returncode
+ except subprocess.CalledProcessError as e:
+ print(f"Error running command: {cmd}")
+ print(f"Error: {e.stderr}")
+ sys.exit(1)
+
+
+def hex_to_rgb(hex_color):
+ """Convert hex color to RGB values (0-1 range)."""
+ hex_color = hex_color.lstrip('#')
+ r = int(hex_color[0:2], 16) / 255.0
+ g = int(hex_color[2:4], 16) / 255.0
+ b = int(hex_color[4:6], 16) / 255.0
+ return r, g, b
+
+
+def run_wal(image_path=None, backend="haishoku"):
+ """Run pywal to generate colors."""
+ if image_path:
+ if not os.path.exists(image_path):
+ print(f"Error: Image file not found: {image_path}")
+ sys.exit(1)
+ print(f"Running wal on image: {image_path} (backend: {backend})")
+ cmd = f'wal -i "{image_path}" --backend {backend}'
+ else:
+ print("Running wal to regenerate colors from last image...")
+ cmd = "wal -n"
+
+ stdout, stderr, returncode = run_command(cmd, check=False)
+
+ if returncode != 0:
+ print(f"\nError: wal failed to process the image.")
+ if stderr:
+ print(f"Details: {stderr}")
+
+ if not image_path:
+ print("Cannot retry without image path. Please specify an image.")
+ sys.exit(1)
+
+ # Try alternative backends as fallback
+ fallback_backends = ["colorthief", "colorz", "wal"]
+
+ for fallback_backend in fallback_backends:
+ if fallback_backend == backend:
+ continue
+ print(f"\nTrying with {fallback_backend} backend...")
+ cmd_fallback = f'wal -i "{image_path}" --backend {fallback_backend}'
+ stdout, stderr, returncode = run_command(cmd_fallback, check=False)
+
+ if returncode == 0:
+ print(f"✓ Successfully generated colors using {fallback_backend} backend")
+ break
+ else:
+ print(f" {fallback_backend} backend also failed")
+ else:
+ print(f"\nError: wal failed with all attempted backends.")
+ print("This may be a pywal bug with this specific image.")
+ print("Suggestions:")
+ print(" - Try a different image")
+ print(" - Update pywal: pip install --upgrade pywal")
+ print(" - Try manually: wal -i <image> --backend <backend>")
+ sys.exit(1)
+
+ if stderr and "error" not in stderr.lower():
+ print(stderr)
+
+ print("✓ Colors generated by wal")
+
+
+
+
+
+def create_dynamic_profile():
+ """Create/update a dynamic profile with pywal colors."""
+ print("Creating/updating dynamic profile...")
+
+ if not COLORS_JSON.exists():
+ print(f"Error: colors.json not found at {COLORS_JSON}")
+ sys.exit(1)
+
+ # Read pywal colors
+ with open(COLORS_JSON) as f:
+ colors = json.load(f)
+
+ colors_dict = colors.get("colors", {})
+ special = colors.get("special", {})
+
+ # Create dynamic profile structure
+ dynamic_profile = {
+ "Profiles": [
+ {
+ "Name": "wal",
+ "Guid": "wal-dynamic-profile-uuid",
+ "Rewritable": True,
+ }
+ ]
+ }
+
+ profile = dynamic_profile["Profiles"][0]
+
+ # Add ANSI colors (0-15)
+ for i in range(16):
+ color_key = f"color{i}"
+ hex_color = colors_dict.get(color_key, "#000000")
+ r, g, b = hex_to_rgb(hex_color)
+ profile[f"Ansi {i} Color"] = {
+ "Color Space": "sRGB",
+ "Red Component": r,
+ "Green Component": g,
+ "Blue Component": b,
+ "Alpha Component": 1.0,
+ }
+
+ # Add special colors
+ profile["Background Color"] = {
+ "Color Space": "sRGB",
+ "Red Component": hex_to_rgb(special.get("background", "#000000"))[0],
+ "Green Component": hex_to_rgb(special.get("background", "#000000"))[1],
+ "Blue Component": hex_to_rgb(special.get("background", "#000000"))[2],
+ "Alpha Component": 1.0,
+ }
+
+ profile["Foreground Color"] = {
+ "Color Space": "sRGB",
+ "Red Component": hex_to_rgb(special.get("foreground", "#ffffff"))[0],
+ "Green Component": hex_to_rgb(special.get("foreground", "#ffffff"))[1],
+ "Blue Component": hex_to_rgb(special.get("foreground", "#ffffff"))[2],
+ "Alpha Component": 1.0,
+ }
+
+ profile["Cursor Color"] = {
+ "Color Space": "sRGB",
+ "Red Component": hex_to_rgb(special.get("cursor", "#ffffff"))[0],
+ "Green Component": hex_to_rgb(special.get("cursor", "#ffffff"))[1],
+ "Blue Component": hex_to_rgb(special.get("cursor", "#ffffff"))[2],
+ "Alpha Component": 1.0,
+ }
+
+ # Write the dynamic profile
+ dynamic_profiles_dir = Path.home() / "Library/Application Support/iTerm2/DynamicProfiles"
+ dynamic_profiles_dir.mkdir(parents=True, exist_ok=True)
+ profile_file = dynamic_profiles_dir / "wal-profile.json"
+
+ with open(profile_file, 'w') as f:
+ json.dump(dynamic_profile, f, indent=2)
+
+ print(f"✓ Dynamic profile created/updated: {profile_file}")
+ print("✓ iTerm2 will automatically detect the changes")
+ print("\nTo use: Switch to the 'wal' profile in iTerm2")
+ print("Future runs will update the 'wal' profile automatically")
+
+
+def main():
+ """Main function."""
+ image_path = sys.argv[1] if len(sys.argv) > 1 else None
+
+ run_wal(image_path, backend="haishoku")
+ create_dynamic_profile()
+
+ print("\n✓ Done! Dynamic profile 'wal' updated with new colors.")
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/scripts/brew.sh b/scripts/brew.sh
new file mode 100755
index 0000000..7ae70d1
--- /dev/null
+++ b/scripts/brew.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env zsh
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
+BREWFILE_PATH="$REPO_ROOT/Brewfile"
+
+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+brew bundle --file "$BREWFILE_PATH" \ No newline at end of file
diff --git a/scripts/omz.sh b/scripts/omz.sh
new file mode 100755
index 0000000..7dd94c3
--- /dev/null
+++ b/scripts/omz.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env zsh
+# Install OMZ
+set -e
+sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
+
+# Powerline fonts
+mkdir -p /tmp/fonts/
+git clone https://github.com/powerline/fonts.git --depth=1 /tmp/fonts/
+chmod +x /tmp/fonts/install.sh
+bash /tmp/fonts/install.sh
+rm -rf /tmp/fonts/
+
+sleep 2s
+
+# Install plugins
+git clone --depth 1 -- https://github.com/zsh-users/zsh-autosuggestions.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
+git clone --depth 1 -- https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
+git clone --depth 1 -- https://github.com/marlonrichert/zsh-autocomplete.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autocomplete
+
+# Overwrite zshrc
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
+cp "$REPO_ROOT/.zshrc" "$HOME/.zshrc" \ No newline at end of file
diff --git a/scripts/setup-mac.sh b/scripts/setup-mac.sh
new file mode 100755
index 0000000..3c16987
--- /dev/null
+++ b/scripts/setup-mac.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env zsh
+# Dock on left
+defaults write com.apple.dock "orientation" -string "left" && killall Dock
+sleep 0.25s
+
+# Set dock icon size
+defaults write com.apple.dock "tilesize" -int "25" && killall Dock
+sleep 0.25s
+
+# Autohide dock
+defaults write com.apple.dock "autohide" -bool "true" && killall Dock
+sleep 0.25s
+
+# Dont show recent apps
+defaults write com.apple.dock "show-recents" -bool "false" && killall Dock
+sleep 0.25s
+
+# Set min animation to scale
+defaults write com.apple.dock "mineffect" -string "scale" && killall Dock
+sleep 0.25s
+
+# Set dock magnification
+defaults write com.apple.dock magnification -bool "true"
+defaults write com.apple.dock largesize -int "48"
+killall Dock
+
+# Save screenshots to downloads
+defaults write com.apple.screencapture "location" -string "~/Downloads" && killall SystemUIServer
+sleep 0.25s
+
+# Set Clock
+defaults write com.apple.menuextra.clock "DateFormat" -string "\"EEE d MMM HH:mm:ss\""
+sleep 0.25s
+
+# Disable the .DS file creation on USB and Network
+defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
+defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true
+sleep 0.25s
+
+# Hide desktop items and Show the path bar in the Finder
+defaults write com.apple.finder "CreateDesktop" -bool "false"
+defaults write com.apple.finder "ShowPathbar" -bool "true" && killall Finder
+sleep 0.25s
+
+# Show hidden files in the Finder
+defaults write com.apple.finder "AppleShowAllFiles" -bool "false" && killall Finder
+sleep 0.25s
+
+# Keep folders on top in Finder
+defaults write com.apple.finder "_FXSortFoldersFirst" -bool "true" && killall Finder
+sleep 0.25s
+
+# Set Key repeat speed
+defaults read NSGlobalDomain InitialKeyRepeat -int 15
+defaults read NSGlobalDomain KeyRepeat -int 2
+sleep 0.25s
+
+# Disable click wallpaper
+defaults write com.apple.WindowManager EnableStandardClickToShowDesktop -bool false
+killall WindowManager
+
+# Apply the settings
+/System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u
+sleep 2s \ No newline at end of file
diff --git a/terminal-profiles/Afterglow.terminal b/terminal-profiles/Afterglow.terminal
new file mode 100644
index 0000000..f07ae81
--- /dev/null
+++ b/terminal-profiles/Afterglow.terminal
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ANSIBlackColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAqMC4wODIzNTI5NDM3MiAwLjA4MjM1Mjk0
+ MzcyIDAuMDgyMzUyOTQzNzIAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlND
+ b2xvcqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+q62vtL/I0NMAAAAAAAABAQAA
+ AAAAAAAZAAAAAAAAAAAAAAAAAAAA3A==
+ </data>
+ <key>ANSIBlueColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAeMC40MjM1Mjk0MTE4IDAuNiAwLjczMzMz
+ MzMzMzMAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xvcqIWGFhOU09i
+ amVjdAgRGiQpMjdJTFFTV11kand+n6GjqLO8xMcAAAAAAAABAQAAAAAAAAAZAAAAAAAA
+ AAAAAAAAAAAA0A==
+ </data>
+ <key>ANSIBrightBlackColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC4zMTM3MjU1MDEzIDAuMzEzNzI1NTAx
+ MyAwLjMxMzcyNTUwMTMAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightBlueColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAeMC40MjM1Mjk0MTE4IDAuNiAwLjczMzMz
+ MzMzMzMAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xvcqIWGFhOU09i
+ amVjdAgRGiQpMjdJTFFTV11kand+n6GjqLO8xMcAAAAAAAABAQAAAAAAAAAZAAAAAAAA
+ AAAAAAAAAAAA0A==
+ </data>
+ <key>ANSIBrightCyanColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40OTAzMTg3OTk5IDAuODM4NTMyMTYy
+ NCAwLjgxMTgxNTE5OTEAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightGreenColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40OTQ3MzgwNDM5IDAuNTU1NzY1Njk1
+ NyAwLjMxNDQ0NjY2NzUAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightMagentaColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC42MjMzMzg1MTgxIDAuMzA2OTc3OTg1
+ OCAwLjUyMzQ0NjY5ODEAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightRedColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC42NzQ1MDk4MjMzIDAuMjU0OTAxOTc1
+ NCAwLjI1ODgyMzU0MzgAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightWhiteColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC45NjA3ODQzMTYxIDAuOTYwNzg0MzE2
+ MSAwLjk2MDc4NDMxNjEAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightYellowColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44OTgwMzkyMTU3IDAuNzA5ODAzOTIx
+ NiAwLjQwMzkyMTU2ODYAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSICyanColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40OTAzMTg3OTk5IDAuODM4NTMyMTYy
+ NCAwLjgxMTgxNTE5OTEAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIGreenColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40OTQ3MzgwNDM5IDAuNTU1NzY1Njk1
+ NyAwLjMxNDQ0NjY2NzUAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIMagentaColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC42MjMzMzg1MTgxIDAuMzA2OTc3OTg1
+ OCAwLjUyMzQ0NjY5ODEAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIRedColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC42NzQ1MDk4MjMzIDAuMjU0OTAxOTc1
+ NCAwLjI1ODgyMzU0MzgAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIWhiteColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44MTU2ODYyODU1IDAuODE1Njg2Mjg1
+ NSAwLjgxNTY4NjI4NTUAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIYellowColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44OTgwMzkyMTU3IDAuNzA5ODAzOTIx
+ NiAwLjQwMzkyMTU2ODYAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>BackgroundColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC4xMjgzNDA2MzkxIDAuMTI4MzQwNjM5
+ MSAwLjEyODM0MDYzOTEAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>Bell</key>
+ <false/>
+ <key>CursorColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44MTU2ODYyODU1IDAuODE1Njg2Mjg1
+ NSAwLjgxNTY4NjI4NTUAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>Font</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGkCwwVFlUkbnVsbNQNDg8QERIT
+ FFZOU1NpemVYTlNmRmxhZ3NWTlNOYW1lViRjbGFzcyNAJgAAAAAAABAQgAKAA1xIYWNr
+ LVJlZ3VsYXLSFxgZGlokY2xhc3NuYW1lWCRjbGFzc2VzVk5TRm9udKIZG1hOU09iamVj
+ dAgRGiQpMjdJTFFTWF5nbnd+hY6QkpShprG6wcQAAAAAAAABAQAAAAAAAAAcAAAAAAAA
+ AAAAAAAAAAAAzQ==
+ </data>
+ <key>FontAntialias</key>
+ <true/>
+ <key>ProfileCurrentVersion</key>
+ <real>2.0699999999999998</real>
+ <key>SelectionColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC4xODgyMzUyOTc4IDAuMTg4MjM1Mjk3
+ OCAwLjE4ODIzNTI5NzgAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>TextBoldColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44MTU2ODYyODU1IDAuODE1Njg2Mjg1
+ NSAwLjgxNTY4NjI4NTUAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>TextColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44MTU2ODYyODU1IDAuODE1Njg2Mjg1
+ NSAwLjgxNTY4NjI4NTUAEAKAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>VisualBell</key>
+ <false/>
+ <key>columnCount</key>
+ <integer>140</integer>
+ <key>name</key>
+ <string>Afterglow</string>
+ <key>rowCount</key>
+ <integer>35</integer>
+ <key>type</key>
+ <string>Window Settings</string>
+ <key>useOptionAsMetaKey</key>
+ <true/>
+</dict>
+</plist>
diff --git a/terminal-profiles/Nord.terminal b/terminal-profiles/Nord.terminal
new file mode 100644
index 0000000..4794f97
--- /dev/null
+++ b/terminal-profiles/Nord.terminal
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ANSIBlackColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC4xNzY0NzA1ODgyIDAuMTk2MDc4NDMx
+ NCAwLjI1NDkwMTk2MDgAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBlueColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40Mjc0NTA5ODA0IDAuNTU2ODYyNzQ1
+ MSAwLjcwOTgwMzkyMTYAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightBlackColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAlMC4yMzEzNzI1NDkgMC4yNjI3NDUwOTgg
+ MC4zNDUwOTgwMzkyABABgALSFBUWF1okY2xhc3NuYW1lWCRjbGFzc2VzV05TQ29sb3Ki
+ FhhYTlNPYmplY3QIERokKTI3SUxRU1ddZGp3fqaoqq+6w8vOAAAAAAAAAQEAAAAAAAAA
+ GQAAAAAAAAAAAAAAAAAAANc=
+ </data>
+ <key>ANSIBrightBlueColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40Mjc0NTA5ODA0IDAuNTU2ODYyNzQ1
+ MSAwLjcwOTgwMzkyMTYAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightCyanColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40ODYyNzQ1MDk4IDAuNjg2Mjc0NTA5
+ OCAwLjY3ODQzMTM3MjUAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightGreenColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC41NzI1NDkwMTk2IDAuNzA1ODgyMzUy
+ OSAwLjQ2NjY2NjY2NjcAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightMagentaColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC42NDcwNTg4MjM1IDAuNDcwNTg4MjM1
+ MyAwLjYxOTYwNzg0MzEAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightRedColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAmMC42OTQxMTc2NDcxIDAuMjkwMTk2MDc4
+ NCAwLjMzNzI1NDkwMgAQAYAC0hQVFhdaJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9y
+ ohYYWE5TT2JqZWN0CBEaJCkyN0lMUVNXXWRqd36nqauwu8TMzwAAAAAAAAEBAAAAAAAA
+ ABkAAAAAAAAAAAAAAAAAAADY
+ </data>
+ <key>ANSIBrightWhiteColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC45MDU4ODIzNTI5IDAuOTIxNTY4NjI3
+ NSAwLjk0NTA5ODAzOTIAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIBrightYellowColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC45MDE5NjA3ODQzIDAuNzYwNzg0MzEz
+ NyAwLjQ1NDkwMTk2MDgAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSICyanColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC40NTg4MjM1Mjk0IDAuNzAxOTYwNzg0
+ MyAwLjc4MDM5MjE1NjkAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIGreenColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC41NzI1NDkwMTk2IDAuNzA1ODgyMzUy
+ OSAwLjQ2NjY2NjY2NjcAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIMagentaColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC42NDcwNTg4MjM1IDAuNDcwNTg4MjM1
+ MyAwLjYxOTYwNzg0MzEAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIRedColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAmMC42OTQxMTc2NDcxIDAuMjkwMTk2MDc4
+ NCAwLjMzNzI1NDkwMgAQAYAC0hQVFhdaJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9y
+ ohYYWE5TT2JqZWN0CBEaJCkyN0lMUVNXXWRqd36nqauwu8TMzwAAAAAAAAEBAAAAAAAA
+ ABkAAAAAAAAAAAAAAAAAAADY
+ </data>
+ <key>ANSIWhiteColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44NzQ1MDk4MDM5IDAuODkwMTk2MDc4
+ NCAwLjkyOTQxMTc2NDcAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>ANSIYellowColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC45MDE5NjA3ODQzIDAuNzYwNzg0MzEz
+ NyAwLjQ1NDkwMTk2MDgAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>BackgroundBlur</key>
+ <real>0.0</real>
+ <key>BackgroundBlurInactive</key>
+ <real>0.35006322552358482</real>
+ <key>BackgroundColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+ EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+ b3JTcGFjZVYkY2xhc3NPECgwLjE2Mjg5MjI1MjIgMC4xOTA5MzUyNTQxIDAuMjEyMzE0
+ NDI2OSAxTxAnMC4xMjI2MTI5NjgxIDAuMTQzMjY2NzY3MyAwLjE2MDI1MTAwNjUAEAGA
+ AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+ WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+ 1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+ AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+ AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+ FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+ UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+ ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+ EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+ AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+ AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+ AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+ RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+ Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+ SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+ IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+ E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+ AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+ AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+ AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+ 8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+ AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+ cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+ A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+ 0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+ BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+ MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+ ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+ pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+ D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+ RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+ FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+ IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+ HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+ SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+ JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+ zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+ MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+ wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+ O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+ MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+ SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+ J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+ V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+ s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+ aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+ 4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+ ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+ uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+ jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+ TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+ o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+ oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+ urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+ w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+ 08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+ veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+ 7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+ mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+ oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+ ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+ Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+ </data>
+ <key>BackgroundSettingsForInactiveWindows</key>
+ <true/>
+ <key>CursorBlink</key>
+ <true/>
+ <key>CursorColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44MTE3NjQ3MDU5IDAuODM5MjE1Njg2
+ MyAwLjg5NDExNzY0NzEAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>CursorType</key>
+ <integer>2</integer>
+ <key>Font</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGkCwwVFlUkbnVsbNQNDg8QERIT
+ FFZOU1NpemVYTlNmRmxhZ3NWTlNOYW1lViRjbGFzcyNAJgAAAAAAABAQgAKAA1xIYWNr
+ LVJlZ3VsYXLSFxgZGlokY2xhc3NuYW1lWCRjbGFzc2VzVk5TRm9udKIZG1hOU09iamVj
+ dAgRGiQpMjdJTFFTWF5nbnd+hY6QkpShprG6wcQAAAAAAAABAQAAAAAAAAAcAAAAAAAA
+ AAAAAAAAAAAAzQ==
+ </data>
+ <key>FontAntialias</key>
+ <true/>
+ <key>ProfileCurrentVersion</key>
+ <real>2.0699999999999998</real>
+ <key>SelectionColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAeMC4yIDAuMjI3NDUwOTgwNCAwLjI5ODAz
+ OTIxNTcAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xvcqIWGFhOU09i
+ amVjdAgRGiQpMjdJTFFTV11kand+n6GjqLO8xMcAAAAAAAABAQAAAAAAAAAZAAAAAAAA
+ AAAAAAAAAAAA0A==
+ </data>
+ <key>TextBoldColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44MTE3NjQ3MDU5IDAuODM5MjE1Njg2
+ MyAwLjg5NDExNzY0NzEAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>TextColor</key>
+ <data>
+ YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+ AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGjCwwTVSRudWxs0w0ODxARElVO
+ U1JHQlxOU0NvbG9yU3BhY2VWJGNsYXNzTxAnMC44MTE3NjQ3MDU5IDAuODM5MjE1Njg2
+ MyAwLjg5NDExNzY0NzEAEAGAAtIUFRYXWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xv
+ cqIWGFhOU09iamVjdAgRGiQpMjdJTFFTV11kand+qKqssbzFzdAAAAAAAAABAQAAAAAA
+ AAAZAAAAAAAAAAAAAAAAAAAA2Q==
+ </data>
+ <key>UseBrightBold</key>
+ <false/>
+ <key>WindowTitle</key>
+ <string>Nord</string>
+ <key>columnCount</key>
+ <integer>140</integer>
+ <key>name</key>
+ <string>Nord</string>
+ <key>rowCount</key>
+ <integer>35</integer>
+ <key>type</key>
+ <string>Window Settings</string>
+</dict>
+</plist>