diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4e874c1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,18 @@ +[submodule "root/usr/share/zsh/site-functions/zsh-autosuggestions"] + path = root/usr/share/zsh/site-functions/zsh-autosuggestions + url = https://github.com/zsh-users/zsh-autosuggestions +[submodule "root/usr/share/zsh/site-functions/zsh-syntax-highlighting"] + path = root/usr/share/zsh/site-functions/zsh-syntax-highlighting + url = https://github.com/zsh-users/zsh-syntax-highlighting +; [submodule "root/usr/share/zsh/site-functions/zsh-you-should-use"] +; path = root/usr/share/zsh/site-functions/zsh-you-should-use +; url = https://github.com/MichaelAquilina/zsh-you-should-use +[submodule "root/usr/local/src/z.lua"] + path = root/usr/local/src/z.lua + url = https://github.com/skywind3000/z.lua +[submodule "root/usr/local/src/Hyprland"] + path = root/usr/local/src/Hyprland + url = https://github.com/hyprwm/Hyprland +[submodule "root/usr/local/src/eww"] + path = root/usr/local/src/eww + url = https://github.com/elkowar/eww diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/firefox/chrome/userChrome.css b/firefox/chrome/userChrome.css new file mode 100644 index 0000000..cc19d5a --- /dev/null +++ b/firefox/chrome/userChrome.css @@ -0,0 +1,6 @@ +@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* only needed once */ + +/* full screen toolbars */ +#navigator-toolbox[inFullscreen] toolbar:not([collapsed="true"]) { + visibility:visible!important; +} diff --git a/firefox/ublock-My_filters.txt b/firefox/ublock-My_filters.txt new file mode 100644 index 0000000..0483398 --- /dev/null +++ b/firefox/ublock-My_filters.txt @@ -0,0 +1,51 @@ +! Replace third-party frames with a click2load banner +*$3p,frame,redirect=click2load.html + +! click2load exceptions +@@||viewscreen.githubusercontent.com^$3p,frame,domain=github.com +@@||www.redditmedia.com^$3p,frame,domain=www.reddit.com +@@||cdn.embedly.com^$3p,frame +@@||imgur.com^$3p,frame + +! Bad TLDs (from https://github.com/DandelionSprout/adfilt/blob/master/Dandelion%20Sprout's%20Anti-Malware%20List.txt) +||agency^ +||bid^ +||cf^ +||ga^ +||gdn^ +||gq^ +||ooo^ +||loan^ +||ml^,domain=~lingva.ml +||pw^ +||tk^ +||top^ + +! Hide GDPR consent banners +sat1.de##cmp-banner +!meteoblue.com##.gdpr_message +askubuntu.com##.js-consent-banner +stackexchange.com##.js-consent-banner +stackoverflow.com##.js-consent-banner +gitbook.io##.r-1yzf0co.r-ymttw5.r-18u37iz.r-1quu1zo.r-1i7sdiz.r-rs99b7.r-156hn8l.r-1habvwh.css-1dbjc4n +www.morgenpost.de##.footer .no-js +www.morgenpost.de##+js(remove-class, no-js, html) + +! Hide/Block annoying elements +stackoverflow.com###saves-launch-popover + +! Hide/Block ad banners + +! Privacy +||collector.github.com^ +||api.github.com/_private/browser/errors +||cmp.zdf.de^ +||discord.com/api/v*/science + +! XSS hardening on codebergs login page +||codeberg.org/user/login^$script +||codeberg.org/user/login^$inline-script +||codeberg.org/user/login^$third-party + +! Badfilters +meteoblue.com#@#.social-wrapper diff --git a/firefox/ublock-My_rules.txt b/firefox/ublock-My_rules.txt new file mode 100644 index 0000000..c8116b3 --- /dev/null +++ b/firefox/ublock-My_rules.txt @@ -0,0 +1,158 @@ +!! This is not a comment, this is a invalid line which gets silently dropped +!! by uB if you paste into your dynamic filter rules + +!! Blocking mode: hard mode with click2load 3p-frames +* * * noop +* * 1p-script noop +* * 3p block +* * 3p-frame noop +* * 3p-script block +* * image noop +* * inline-script noop +behind-the-scene * * block + +!! Global CDN noops for common CDNs (mostly via CNAME) +* akamai.net * noop +* akamaiedge.net * noop +* akamaihd.net * noop +* akamaized.net * noop +* b-cdn.net * noop +* cdn.cloudflare.net * noop +* cloudfront.net * noop +* discourse-cdn.com * noop +* edgecastcdn.net * noop +* global.fastly.net * noop +* hwcdn.net * noop +* kxcdn.com * noop +* bootstrapcdn.com * noop +* map.fastly.net * noop +* netdna-ssl.com * noop +* wp.com * noop +* ajax.googleapis.com * noop +* jsdelivr.net * noop +* unsplash.com * noop +* cdn.embedly.com * noop +* wixmp.com * noop + +!! Website building/caching tools +* cloudflare.com * noop +* prismic.io * noop +* googlehosted.com * noop + +!! Website 3rd party utilities (trusted or simply necessary things) +* maps.googleapis.com * noop +* recaptcha.net * noop +* imgur.com * noop +* shields.io * noop +* gravatar.com * noop + +!! Explicit blocks (even though we block all 3rd parties, explicitly block these to signify that they're evil) +* fonts.googleapis.com * block +* doubleclick.net * block +* sentry.io * block +* servedby-buysellads.com * block +* facebook.com * block +* facebook.net * block + +!! Per-site (mostly noop) settings + +! GitHub +github.com avatars.githubusercontent.com * noop +github.com githubassets.com * noop + +! Google +accounts.google.com googleusercontent.com * noop +accounts.google.com gstatic.com * noop +accounts.google.com signaler-pa.googleapis.com * noop +accounts.google.com youtube.com * noop + +developers.google.com gstatic.com * noop +developers.google.com googleusercontent.com * noop + +drive.google.com googleusercontent.com * noop +drive.google.com gstatic.com * noop + +docs.google.com googleusercontent.com * noop +docs.google.com gstatic.com * noop + +mail.google.com googleusercontent.com * noop +mail.google.com gstatic.com * noop + +translate.google.com googleusercontent.com * noop +translate.google.com gstatic.com * noop + +www.youtube.com ggpht.com * noop +www.youtube.com google.com * noop +www.youtube.com googleusercontent.com * noop +www.youtube.com googlevideo.com * noop +www.youtube.com gstatic.com * noop +www.youtube.com jnn-pa.googleapis.com * noop +www.youtube.com ytimg.com * noop + +! Microsoft crap +login.live.com * 3p noop +login.live.com * 3p-frame noop +login.live.com * 3p-script noop + +login.microsoftonline.com * 3p noop +login.microsoftonline.com * 3p-frame noop +login.microsoftonline.com * 3p-script noop + +outlook.live.com * 3p noop +outlook.live.com * 3p-frame noop +outlook.live.com * 3p-script noop + +outlook.office365.com * 3p noop +outlook.office365.com * 3p-frame noop +outlook.office365.com * 3p-script noop + +! Protonmail +mail.proton.me * 3p noop +mail.proton.me * 3p-frame noop +mail.proton.me * 3p-script noop + +! Reddit +www.reddit.com redditmedia.com * noop +www.reddit.com redditstatic.com * noop +www.reddit.com redd.it * noop + +! StackExchange +stackexchange.com sstatic.net * noop +stackexchange.com stackoverflow.com * noop + +stackoverflow.com sstatic.net * noop +stackoverflow.com stackexchange.com * noop + +askubuntu.com sstatic.net * noop +askubuntu.com stackexchange.com * noop +askubuntu.com stackoverflow.com * noop + +superuser.com sstatic.net * noop +superuser.com stackexchange.com * noop +superuser.com stackoverflow.com * noop + +serverfault.com sstatic.net * noop +serverfault.com stackexchange.com * noop +serverfault.com stackoverflow.com * noop + +! Simplelogin +app.simplelogin.io simplelogin.co * noop + +! Privacyguides +www.privacyguides.org github.com * noop +www.privacyguides.org privacyguides.github.io * noop +www.privacyguides.org privacyguides.net * noop + +! Fontawesome +fontawesome.com algolia.net * noop +fontawesome.com algolianet.com * noop +fontawesome.com fortawesome.com * noop + +! IMDb +www.imdb.com media-amazon.com * noop +www.imdb.com media-imdb.com * noop + +! Others +docs.gtk.org gnome.org * noop +letsgetrusty.com kartra.com * noop +* readthedocs.io * noop diff --git a/firefox/user-overrides.js b/firefox/user-overrides.js new file mode 100644 index 0000000..bcb5bfc --- /dev/null +++ b/firefox/user-overrides.js @@ -0,0 +1,76 @@ +/* --------------- PERSONAL ARKENFOX OVERRIDES --------------- ***/ +user_pref("_overrides.parrot", "Custom: Arkenfox overrides"); + +/* Re-enabled single perf features ***/ +user_pref("keyword.enabled", true); // 0801 Enable searching from location bar (I trust my search engine) +// user_pref("browser.search.suggest.enabled", true); // 0804 Enable search suggestions +// user_pref("browser.urlbar.suggest.searches", true); // 0804 Enables search suggestions in the url-bar +user_pref("network.http.referer.XOriginPolicy", 0); // 1601 Allow cross origin referrers (disabling breaks too much), I use Smart Referer extension instead +user_pref("privacy.clearOnShutdown.sessions", true); // 2811 Retain HTTP Basic Auth on shutdown +user_pref("signon.rememberSignons", false); // 5003 Disable saving passwords to FF, there's Bitwarden +user_pref("security.nocertdb", true); // 5005 Don't cache certificates (stores them session-only) +user_pref("browser.download.folderList", 1); // 5016 Always use default downloads folder, not previous folder for download location + +/* override recipe: enable session restore ***/ +user_pref("browser.startup.page", 3); // 0102 Enable session restore +user_pref("privacy.clearOnShutdown.history", false); // 2811 Don't clear history on exit +user_pref("privacy.cpd.history", false); // 2812 To match when you use Ctrl-Shift-Del +user_pref("places.history.enabled", false); // 5013 Disable browsing and download history (allows no history with session restore) + +/* --------------- PERSONAL PRIVACY RULES --------------- ***/ +user_pref("_overrides.parrot", "Custom: Privacy rules"); + +/* Deny some permission requests by default (prevent ask popups) ***/ +user_pref("permissions.default.microphone", 2); // Microphone +user_pref("permissions.default.desktop-notification", 2); // Notifications +user_pref("permissions.default.geo", 2); // Location + +/* Disable safebrowsing (sends data to google) ***/ +user_pref("browser.safebrowsing.downloads.remote.enabled", false); +user_pref("browser.safebrowsing.phishing.enabled", false); +user_pref("browser.safebrowsing.malware.enabled", false); + +/* Javascript hardening (might cause slowdowns/breakage) ***/ +// user_pref("javascript.options.ion", false); // Might cause slowdowns/breakage +// user_pref("javascript.options.asmjs", false); // Might cause slowdowns/breakage +// user_pref("javascript.options.wasm", false); // Completely disables WASM, for the security gain and speed benefit +// user_pref("javascript.options.baselinejit", false); // Disable JIT compilation - usually breaks sites with a lot of javascript but is a huge security gain + +/* Mark Quad9 as trusted recursive resolver (TRR) for DNS over HTTPS (DoH) ***/ +user_pref("network.trr.mode", 2); // Use TRR first, and only if the secure resolution fails use the operating system resolver. +user_pref("network.trr.uri", "https://dns.quad9.net:5053/dns-query"); // Resolver we want to use +user_pref("network.trr.bootstrapAddress", "9.9.9.9"); // Address to lookup the quad9 DoH address (only used once for this lookup) + +/* Other Privacy hardenings ***/ +user_pref("geo.enabled", false); // Fully disable location access +user_pref("media.hardwaremediakeys.enabled", false); // Disable control via media keys (some websites might be stealing these) +user_pref("dom.webaudio.enabled",false); // Old, mostly unused API, likely utilized for fingerprinting, hasn't broken anything FOR ME + +/* --------------- PERSONAL NON-PRIVACY RULES --------------- ***/ +user_pref("_overrides.parrot", "Custom: Non-privacy rules"); + +/* Annoyances ***/ +user_pref("browser.tabs.firefox-view", false); // Don't show firefox view tab +user_pref("extensions.pocket.enabled", false); // Disable pocket +user_pref("extensions.abuseReport.enabled", false); // Disable report extension to mozilla +user_pref("identity.fxaccounts.enabled", false); // Disable sync entirely + +/* Urlbar suggestions ***/ +user_pref("browser.urlbar.suggest.openpage", false); // Disable suggestions of open pages +user_pref("browser.urlbar.suggest.engines", false); // Disable suggestions of search engines +user_pref("browser.urlbar.suggest.topsites", false); // Disable suggestions of top sites + +/* Styling changes ***/ +user_pref("browser.fullscreen.autohide", false); // Don't auto-hide tabs when firefox is in fullscreen +user_pref("browser.toolbars.bookmarks.visibility", "always"); // Always show bookmarks toolbar +user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true); // Enable profile customization with userChrome.css and userContent.css +user_pref("ui.systemUsesDarkTheme", 1); // Enables `prefers-color-scheme` CSS media feature + +/* Other changes ***/ +user_pref("browser.preferences.experimental", true); // Show experimental options in about:preferences +user_pref("browser.urlbar.suggest.calculator", true); // Calculator in urlbar +user_pref("layout.spellcheckDefault", 2); // Enable spellcheck by default for all inputs +user_pref("browser.quitShortcut.disabled", true); // Disable Ctrl+Q browser quit shortcut + +/* --------------- END --------------- ***/ +user_pref("_overrides.parrot", "Custom: success"); diff --git a/home/.cache/nv/.keep b/home/.cache/nv/.keep new file mode 100644 index 0000000..e69de29 diff --git a/home/.cache/python_history b/home/.cache/python_history new file mode 100644 index 0000000..e69de29 diff --git a/home/.cache/zsh/history b/home/.cache/zsh/history new file mode 100644 index 0000000..e69de29 diff --git a/home/.config/alacritty/alacritty.yml b/home/.config/alacritty/alacritty.yml new file mode 100644 index 0000000..251749b --- /dev/null +++ b/home/.config/alacritty/alacritty.yml @@ -0,0 +1,816 @@ +# Configuration for Alacritty, the GPU enhanced terminal emulator. + +# Import additional configuration files +# +# Imports are loaded in order, skipping all missing files, with the importing +# file being loaded last. If a field is already present in a previous import, it +# will be replaced. +# +# All imports must either be absolute paths starting with `/`, or paths relative +# to the user's home directory starting with `~/`. +#import: +# - /path/to/alacritty.yml + +# Any items in the `env` entry below will be added as +# environment variables. Some entries may override variables +# set by alacritty itself. +#env: + # TERM variable + # + # This value is used to set the `$TERM` environment variable for + # each instance of Alacritty. If it is not present, alacritty will + # check the local terminfo database and use `alacritty` if it is + # available, otherwise `xterm-256color` is used. + #TERM: alacritty + +window: + # Window dimensions (changes require restart) + # + # Number of lines/columns (not pixels) in the terminal. The number of columns + # must be at least `2`, while using a value of `0` for columns and lines will + # fall back to the window manager's recommended size. + #dimensions: + # columns: 0 + # lines: 0 + + # Window position (changes require restart) + # + # Specified in number of pixels. + # If the position is not set, the window manager will handle the placement. + #position: + # x: 0 + # y: 0 + + # Window padding (changes require restart) + # + # Blank space added around the window in pixels. This padding is scaled + # by DPI and the specified value is always added at both opposing sides. + padding: + x: 6 + y: 6 + + # Background opacity + # + # Window opacity as a floating point number from `0.0` to `1.0`. + # The value `0.0` is completely transparent and `1.0` is opaque. + opacity: 0.9 + + # Spread additional padding evenly around the terminal content. + #dynamic_padding: false + + # Window decorations + # + # Values for `decorations`: + # - full: Borders and title bar + # - none: Neither borders nor title bar + # + # Values for `decorations` (macOS only): + # - transparent: Title bar, transparent background and title bar buttons + # - buttonless: Title bar, transparent background and no title bar buttons + #decorations: full + + # Startup Mode (changes require restart) + # + # Values for `startup_mode`: + # - Windowed + # - Maximized + # - Fullscreen + # + # Values for `startup_mode` (macOS only): + # - SimpleFullscreen + #startup_mode: Windowed + + # Window title + #title: Alacritty + + # Allow terminal applications to change Alacritty's window title. + #dynamic_title: true + + # Window class (Linux/BSD only): + #class: + # Application instance name + #instance: Alacritty + # General application class + #general: Alacritty + + # GTK theme variant (Linux/BSD only) + # + # Override the variant of the GTK theme. Commonly supported values are `dark` + # and `light`. Set this to `None` to use the default theme variant. + #gtk_theme_variant: None + +scrolling: + # Maximum number of lines in the scrollback buffer. + # Specifying '0' will disable scrolling. + history: 10000 + + # Scrolling distance multiplier. + #multiplier: 3 + +# Font configuration +font: + # Normal (roman) font face + normal: + # Font family + # + # Default: + # - (macOS) Menlo + # - (Linux/BSD) monospace + # - (Windows) Consolas + family: JetBrains Mono + #family: Comic Mono + #family: Source Code Pro + + # The `style` can be specified to pick a specific face. + style: Medium + + # Bold font face + #bold: + # Font family + # + # If the bold family is not specified, it will fall back to the + # value specified for the normal font. + #family: monospace + #family: Source Code Pro + + # The `style` can be specified to pick a specific face. + #style: Bold + + # Italic font face + #italic: + # Font family + # + # If the italic family is not specified, it will fall back to the + # value specified for the normal font. + #family: monospace + #family: Source Code Pro + + # The `style` can be specified to pick a specific face. + #style: Italic + + # Bold italic font face + #bold_italic: + # Font family + # + # If the bold italic family is not specified, it will fall back to the + # value specified for the normal font. + #family: monospace + + # The `style` can be specified to pick a specific face. + #style: Bold Italic + + # Point size + size: 11.0 + + # Offset is the extra space around each character. `offset.y` can be thought + # of as modifying the line spacing, and `offset.x` as modifying the letter + # spacing. + #offset: + # x: 0 + # y: 0 + + # Glyph offset determines the locations of the glyphs within their cells with + # the default being at the bottom. Increasing `x` moves the glyph to the + # right, increasing `y` moves the glyph upward. + #glyph_offset: + # x: 0 + # y: 0 + + # Thin stroke font rendering (macOS only) + # + # Thin strokes are suitable for retina displays, but for non-retina screens + # it is recommended to set `use_thin_strokes` to `false`. + #use_thin_strokes: true + +# If `true`, bold text is drawn using the bright color variants. +draw_bold_text_with_bright_colors: false + +# Colors (Tomorrow Night) +colors: + # Default colors + primary: + background: '#191919' + foreground: '#d8dee9' + #background: '#1d1f21' + #foreground: '#c5c8c6' + + # Bright and dim foreground colors + # + # The dimmed foreground color is calculated automatically if it is not + # present. If the bright foreground color is not set, or + # `draw_bold_text_with_bright_colors` is `false`, the normal foreground + # color will be used. + #dim_foreground: '#828482' + #bright_foreground: '#eaeaea' + + # Cursor colors + # + # Colors which should be used to draw the terminal cursor. + # + # Allowed values are CellForeground and CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #cursor: + # text: CellBackground + # cursor: CellForeground + + # Vi mode cursor colors + # + # Colors for the cursor when the vi mode is active. + # + # Allowed values are CellForeground and CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #vi_mode_cursor: + # text: CellBackground + # cursor: CellForeground + + # Search colors + # + # Colors used for the search bar and match highlighting. + #search: + # Allowed values are CellForeground and CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #matches: + # foreground: '#000000' + # background: '#ffffff' + #focused_match: + # foreground: CellBackground + # background: CellForeground + + #bar: + # background: '#c5c8c6' + # foreground: '#1d1f21' + + # Line indicator + # + # Color used for the indicator displaying the position in history during + # search and vi mode. + # + # By default, these will use the opposing primary color. + #line_indicator: + # foreground: None + # background: None + + # Selection colors + # + # Colors which should be used to draw the selection area. + # + # Allowed values are CellForeground and CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #selection: + # text: CellBackground + # background: CellForeground + + # Normal colors + normal: + #black: '#191919' + black: '#46494d' + red: '#b02626' + green: '#40a62f' + yellow: '#f2e635' + blue: '#314ad0' + magenta: '#b30ad0' + cyan: '#32d0fc' + white: '#acadb1' + + # Bright colors + bright: + black: '#666666' + red: '#ce2727' + green: '#47c930' + yellow: '#fff138' + blue: '#2e4bea' + magenta: '#cc15ed' + cyan: '#54d9ff' + white: '#dbdbdb' + + # Dim colors + dim: + black: '#676f78' + red: '#b55454' + green: '#78a670' + yellow: '#faf380' + blue: '#707fd0' + magenta: '#c583d0' + cyan: '#8adaf1' + white: '#e0e3e7' + + # Indexed Colors + # + # The indexed colors include all colors from 16 to 256. + # When these are not set, they're filled with sensible defaults. + # + # Example: + # `- { index: 16, color: '#ff00ff' }` + # + #indexed_colors: [] + +# Bell +# +# The bell is rung every time the BEL control character is received. +#bell: + # Visual Bell Animation + # + # Animation effect for flashing the screen when the visual bell is rung. + # + # Values for `animation`: + # - Ease + # - EaseOut + # - EaseOutSine + # - EaseOutQuad + # - EaseOutCubic + # - EaseOutQuart + # - EaseOutQuint + # - EaseOutExpo + # - EaseOutCirc + # - Linear + #animation: EaseOutExpo + + # Duration of the visual bell flash in milliseconds. A `duration` of `0` will + # disable the visual bell animation. + #duration: 0 + + # Visual bell animation color. + #color: '#ffffff' + + # Bell Command + # + # This program is executed whenever the bell is rung. + # + # When set to `command: None`, no command will be executed. + # + # Example: + # command: + # program: notify-send + # args: ["Hello, World!"] + # + #command: None + +#selection: + # This string contains all characters that are used as separators for + # "semantic words" in Alacritty. + #semantic_escape_chars: ",│`|:\"' ()[]{}<>\t" + + # When set to `true`, selected text will be copied to the primary clipboard. + #save_to_clipboard: false + +#cursor: + # Cursor style + #style: + # Cursor shape + # + # Values for `shape`: + # - ▇ Block + # - _ Underline + # - | Beam + #shape: Block + + # Cursor blinking state + # + # Values for `blinking`: + # - Never: Prevent the cursor from ever blinking + # - Off: Disable blinking by default + # - On: Enable blinking by default + # - Always: Force the cursor to always blink + #blinking: Off + + # Vi mode cursor style + # + # If the vi mode cursor style is `None` or not specified, it will fall back to + # the style of the active value of the normal cursor. + # + # See `cursor.style` for available options. + #vi_mode_style: None + + # Cursor blinking interval in milliseconds. + #blink_interval: 750 + + # If this is `true`, the cursor will be rendered as a hollow box when the + # window is not focused. + #unfocused_hollow: true + + # Thickness of the cursor relative to the cell width as floating point number + # from `0.0` to `1.0`. + #thickness: 0.15 + +# Live config reload (changes require restart) +#live_config_reload: true + +# Shell +# +# You can set `shell.program` to the path of your favorite shell, e.g. +# `/bin/fish`. Entries in `shell.args` are passed unmodified as arguments to the +# shell. +# +# Default: +# - (macOS) /bin/bash --login +# - (Linux/BSD) user login shell +# - (Windows) powershell +#shell: +# program: /bin/bash +# args: +# - --login + +# Startup directory +# +# Directory the shell is started in. If this is unset, or `None`, the working +# directory of the parent process will be used. +#working_directory: None + +# Send ESC (\x1b) before characters when alt is pressed. +#alt_send_esc: true + +#mouse: + # Click settings + # + # The `double_click` and `triple_click` settings control the time + # alacritty should wait for accepting multiple clicks as one double + # or triple click. + #double_click: { threshold: 300 } + #triple_click: { threshold: 300 } + + # If this is `true`, the cursor is temporarily hidden when typing. + #hide_when_typing: false + + #url: + # URL launcher + # + # This program is executed when clicking on a text which is recognized as a + # URL. The URL is always added to the command as the last parameter. + # + # When set to `launcher: None`, URL launching will be disabled completely. + # + # Default: + # - (macOS) open + # - (Linux/BSD) xdg-open + # - (Windows) explorer + #launcher: + # program: xdg-open + # args: [] + + # URL modifiers + # + # These are the modifiers that need to be held down for opening URLs when + # clicking on them. The available modifiers are documented in the key + # binding section. + #modifiers: None + +# Mouse bindings +# +# Mouse bindings are specified as a list of objects, much like the key +# bindings further below. +# +# To trigger mouse bindings when an application running within Alacritty +# captures the mouse, the `Shift` modifier is automatically added as a +# requirement. +# +# Each mouse binding will specify a: +# +# - `mouse`: +# +# - Middle +# - Left +# - Right +# - Numeric identifier such as `5` +# +# - `action` (see key bindings) +# +# And optionally: +# +# - `mods` (see key bindings) +#mouse_bindings: +# - { mouse: Middle, action: PasteSelection } + +# Key bindings +# +# Key bindings are specified as a list of objects. For example, this is the +# default paste binding: +# +# `- { key: V, mods: Control|Shift, action: Paste }` +# +# Each key binding will specify a: +# +# - `key`: Identifier of the key pressed +# +# - A-Z +# - F1-F24 +# - Key0-Key9 +# +# A full list with available key codes can be found here: +# https://docs.rs/glutin/*/glutin/event/enum.VirtualKeyCode.html#variants +# +# Instead of using the name of the keys, the `key` field also supports using +# the scancode of the desired key. Scancodes have to be specified as a +# decimal number. This command will allow you to display the hex scancodes +# for certain keys: +# +# `showkey --scancodes`. +# +# Then exactly one of: +# +# - `chars`: Send a byte sequence to the running application +# +# The `chars` field writes the specified string to the terminal. This makes +# it possible to pass escape sequences. To find escape codes for bindings +# like `PageUp` (`"\x1b[5~"`), you can run the command `showkey -a` outside +# of tmux. Note that applications use terminfo to map escape sequences back +# to keys. It is therefore required to update the terminfo when changing an +# escape sequence. +# +# - `action`: Execute a predefined action +# +# - ToggleViMode +# - SearchForward +# Start searching toward the right of the search origin. +# - SearchBackward +# Start searching toward the left of the search origin. +# - Copy +# - Paste +# - IncreaseFontSize +# - DecreaseFontSize +# - ResetFontSize +# - ScrollPageUp +# - ScrollPageDown +# - ScrollHalfPageUp +# - ScrollHalfPageDown +# - ScrollLineUp +# - ScrollLineDown +# - ScrollToTop +# - ScrollToBottom +# - ClearHistory +# Remove the terminal's scrollback history. +# - Hide +# Hide the Alacritty window. +# - Minimize +# Minimize the Alacritty window. +# - Quit +# Quit Alacritty. +# - ToggleFullscreen +# - SpawnNewInstance +# Spawn a new instance of Alacritty. +# - ClearLogNotice +# Clear Alacritty's UI warning and error notice. +# - ClearSelection +# Remove the active selection. +# - ReceiveChar +# - None +# +# - Vi mode exclusive actions: +# +# - Open +# Open URLs at the cursor location with the launcher configured in +# `url.launcher`. +# - ToggleNormalSelection +# - ToggleLineSelection +# - ToggleBlockSelection +# - ToggleSemanticSelection +# Toggle semantic selection based on `selection.semantic_escape_chars`. +# +# - Vi mode exclusive cursor motion actions: +# +# - Up +# One line up. +# - Down +# One line down. +# - Left +# One character left. +# - Right +# One character right. +# - First +# First column, or beginning of the line when already at the first column. +# - Last +# Last column, or beginning of the line when already at the last column. +# - FirstOccupied +# First non-empty cell in this terminal row, or first non-empty cell of +# the line when already at the first cell of the row. +# - High +# Top of the screen. +# - Middle +# Center of the screen. +# - Low +# Bottom of the screen. +# - SemanticLeft +# Start of the previous semantically separated word. +# - SemanticRight +# Start of the next semantically separated word. +# - SemanticLeftEnd +# End of the previous semantically separated word. +# - SemanticRightEnd +# End of the next semantically separated word. +# - WordLeft +# Start of the previous whitespace separated word. +# - WordRight +# Start of the next whitespace separated word. +# - WordLeftEnd +# End of the previous whitespace separated word. +# - WordRightEnd +# End of the next whitespace separated word. +# - Bracket +# Character matching the bracket at the cursor's location. +# - SearchNext +# Beginning of the next match. +# - SearchPrevious +# Beginning of the previous match. +# - SearchStart +# Start of the match to the left of the vi mode cursor. +# - SearchEnd +# End of the match to the right of the vi mode cursor. +# +# - Search mode exclusive actions: +# - SearchFocusNext +# Move the focus to the next search match. +# - SearchFocusPrevious +# Move the focus to the previous search match. +# - SearchConfirm +# - SearchCancel +# - SearchClear +# Reset the search regex. +# - SearchDeleteWord +# Delete the last word in the search regex. +# - SearchHistoryPrevious +# Go to the previous regex in the search history. +# - SearchHistoryNext +# Go to the next regex in the search history. +# +# - macOS exclusive actions: +# - ToggleSimpleFullscreen +# Enter fullscreen without occupying another space. +# +# - Linux/BSD exclusive actions: +# +# - CopySelection +# Copy from the selection buffer. +# - PasteSelection +# Paste from the selection buffer. +# +# - `command`: Fork and execute a specified command plus arguments +# +# The `command` field must be a map containing a `program` string and an +# `args` array of command line parameter strings. For example: +# `{ program: "alacritty", args: ["-e", "vttest"] }` +# +# And optionally: +# +# - `mods`: Key modifiers to filter binding actions +# +# - Command +# - Control +# - Option +# - Super +# - Shift +# - Alt +# +# Multiple `mods` can be combined using `|` like this: +# `mods: Control|Shift`. +# Whitespace and capitalization are relevant and must match the example. +# +# - `mode`: Indicate a binding for only specific terminal reported modes +# +# This is mainly used to send applications the correct escape sequences +# when in different modes. +# +# - AppCursor +# - AppKeypad +# - Search +# - Alt +# - Vi +# +# A `~` operator can be used before a mode to apply the binding whenever +# the mode is *not* active, e.g. `~Alt`. +# +# Bindings are always filled by default, but will be replaced when a new +# binding with the same triggers is defined. To unset a default binding, it can +# be mapped to the `ReceiveChar` action. Alternatively, you can use `None` for +# a no-op if you do not wish to receive input characters for that binding. +# +# If the same trigger is assigned to multiple actions, all of them are executed +# in the order they were defined in. +#key_bindings: + #- { key: Paste, action: Paste } + #- { key: Copy, action: Copy } + #- { key: L, mods: Control, action: ClearLogNotice } + #- { key: L, mods: Control, mode: ~Vi|~Search, chars: "\x0c" } + #- { key: PageUp, mods: Shift, mode: ~Alt, action: ScrollPageUp, } + #- { key: PageDown, mods: Shift, mode: ~Alt, action: ScrollPageDown } + #- { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop, } + #- { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom } + + # Vi Mode + #- { key: Space, mods: Shift|Control, mode: Vi|~Search, action: ScrollToBottom } + #- { key: Space, mods: Shift|Control, mode: ~Search, action: ToggleViMode } + #- { key: Escape, mode: Vi|~Search, action: ClearSelection } + #- { key: I, mode: Vi|~Search, action: ScrollToBottom } + #- { key: I, mode: Vi|~Search, action: ToggleViMode } + #- { key: C, mods: Control, mode: Vi|~Search, action: ToggleViMode } + #- { key: Y, mods: Control, mode: Vi|~Search, action: ScrollLineUp } + #- { key: E, mods: Control, mode: Vi|~Search, action: ScrollLineDown } + #- { key: G, mode: Vi|~Search, action: ScrollToTop } + #- { key: G, mods: Shift, mode: Vi|~Search, action: ScrollToBottom } + #- { key: B, mods: Control, mode: Vi|~Search, action: ScrollPageUp } + #- { key: F, mods: Control, mode: Vi|~Search, action: ScrollPageDown } + #- { key: U, mods: Control, mode: Vi|~Search, action: ScrollHalfPageUp } + #- { key: D, mods: Control, mode: Vi|~Search, action: ScrollHalfPageDown } + #- { key: Y, mode: Vi|~Search, action: Copy } + #- { key: Y, mode: Vi|~Search, action: ClearSelection } + #- { key: Copy, mode: Vi|~Search, action: ClearSelection } + #- { key: V, mode: Vi|~Search, action: ToggleNormalSelection } + #- { key: V, mods: Shift, mode: Vi|~Search, action: ToggleLineSelection } + #- { key: V, mods: Control, mode: Vi|~Search, action: ToggleBlockSelection } + #- { key: V, mods: Alt, mode: Vi|~Search, action: ToggleSemanticSelection } + #- { key: Return, mode: Vi|~Search, action: Open } + #- { key: K, mode: Vi|~Search, action: Up } + #- { key: J, mode: Vi|~Search, action: Down } + #- { key: H, mode: Vi|~Search, action: Left } + #- { key: L, mode: Vi|~Search, action: Right } + #- { key: Up, mode: Vi|~Search, action: Up } + #- { key: Down, mode: Vi|~Search, action: Down } + #- { key: Left, mode: Vi|~Search, action: Left } + #- { key: Right, mode: Vi|~Search, action: Right } + #- { key: Key0, mode: Vi|~Search, action: First } + #- { key: Key4, mods: Shift, mode: Vi|~Search, action: Last } + #- { key: Key6, mods: Shift, mode: Vi|~Search, action: FirstOccupied } + #- { key: H, mods: Shift, mode: Vi|~Search, action: High } + #- { key: M, mods: Shift, mode: Vi|~Search, action: Middle } + #- { key: L, mods: Shift, mode: Vi|~Search, action: Low } + #- { key: B, mode: Vi|~Search, action: SemanticLeft } + #- { key: W, mode: Vi|~Search, action: SemanticRight } + #- { key: E, mode: Vi|~Search, action: SemanticRightEnd } + #- { key: B, mods: Shift, mode: Vi|~Search, action: WordLeft } + #- { key: W, mods: Shift, mode: Vi|~Search, action: WordRight } + #- { key: E, mods: Shift, mode: Vi|~Search, action: WordRightEnd } + #- { key: Key5, mods: Shift, mode: Vi|~Search, action: Bracket } + #- { key: Slash, mode: Vi|~Search, action: SearchForward } + #- { key: Slash, mods: Shift, mode: Vi|~Search, action: SearchBackward } + #- { key: N, mode: Vi|~Search, action: SearchNext } + #- { key: N, mods: Shift, mode: Vi|~Search, action: SearchPrevious } + + # Search Mode + #- { key: Return, mode: Search|Vi, action: SearchConfirm } + #- { key: Escape, mode: Search, action: SearchCancel } + #- { key: C, mods: Control, mode: Search, action: SearchCancel } + #- { key: U, mods: Control, mode: Search, action: SearchClear } + #- { key: W, mods: Control, mode: Search, action: SearchDeleteWord } + #- { key: P, mods: Control, mode: Search, action: SearchHistoryPrevious } + #- { key: N, mods: Control, mode: Search, action: SearchHistoryNext } + #- { key: Up, mode: Search, action: SearchHistoryPrevious } + #- { key: Down, mode: Search, action: SearchHistoryNext } + #- { key: Return, mode: Search|~Vi, action: SearchFocusNext } + #- { key: Return, mods: Shift, mode: Search|~Vi, action: SearchFocusPrevious } + + # (Windows, Linux, and BSD only) + #- { key: V, mods: Control|Shift, mode: ~Vi, action: Paste } + #- { key: C, mods: Control|Shift, action: Copy } + #- { key: F, mods: Control|Shift, mode: ~Search, action: SearchForward } + #- { key: B, mods: Control|Shift, mode: ~Search, action: SearchBackward } + #- { key: C, mods: Control|Shift, mode: Vi|~Search, action: ClearSelection } + #- { key: Insert, mods: Shift, action: PasteSelection } + #- { key: Key0, mods: Control, action: ResetFontSize } + #- { key: Equals, mods: Control, action: IncreaseFontSize } + #- { key: Plus, mods: Control, action: IncreaseFontSize } + #- { key: NumpadAdd, mods: Control, action: IncreaseFontSize } + #- { key: Minus, mods: Control, action: DecreaseFontSize } + #- { key: NumpadSubtract, mods: Control, action: DecreaseFontSize } + + # (Windows only) + #- { key: Return, mods: Alt, action: ToggleFullscreen } + + # (macOS only) + #- { key: K, mods: Command, mode: ~Vi|~Search, chars: "\x0c" } + #- { key: K, mods: Command, mode: ~Vi|~Search, action: ClearHistory } + #- { key: Key0, mods: Command, action: ResetFontSize } + #- { key: Equals, mods: Command, action: IncreaseFontSize } + #- { key: Plus, mods: Command, action: IncreaseFontSize } + #- { key: NumpadAdd, mods: Command, action: IncreaseFontSize } + #- { key: Minus, mods: Command, action: DecreaseFontSize } + #- { key: NumpadSubtract, mods: Command, action: DecreaseFontSize } + #- { key: V, mods: Command, action: Paste } + #- { key: C, mods: Command, action: Copy } + #- { key: C, mods: Command, mode: Vi|~Search, action: ClearSelection } + #- { key: H, mods: Command, action: Hide } + #- { key: M, mods: Command, action: Minimize } + #- { key: Q, mods: Command, action: Quit } + #- { key: W, mods: Command, action: Quit } + #- { key: N, mods: Command, action: SpawnNewInstance } + #- { key: F, mods: Command|Control, action: ToggleFullscreen } + #- { key: F, mods: Command, mode: ~Search, action: SearchForward } + #- { key: B, mods: Command, mode: ~Search, action: SearchBackward } + +#debug: + # Display the time it takes to redraw each frame. + #render_timer: false + + # Keep the log file after quitting Alacritty. + #persistent_logging: false + + # Log level + # + # Values for `log_level`: + # - Off + # - Error + # - Warn + # - Info + # - Debug + # - Trace + #log_level: Warn + + # Print all received window events. + #print_events: false diff --git a/home/.config/dunst/dunstrc b/home/.config/dunst/dunstrc new file mode 100644 index 0000000..59f3213 --- /dev/null +++ b/home/.config/dunst/dunstrc @@ -0,0 +1,443 @@ +[global] + + ### Display ### + + # Which monitor should the notifications be shown on + monitor = 0 + + # Display notifications on focused monitor. Possible modes: + # mouse: follow mouse pointer + # keyboard: follow window with keyboard focus + # none: don't follow anything + # + # keyboard needs a window manager that exports + # _NET_ACTIVE_WINDOW propery! This should be the case for almost + # all modern window managers. + # + # If this option isn't none, monitor option will be ignored. + follow = mouse + + ### Geometry ### + + # Dynamic width from 0 to 300 + # width = (0, 300) + # constant width of 300 + # width = 300 + width = 270 + + # The maximum height of a single notification, excluding the frame. + height = 300 + + # Position the notification in the top right corner + origin = top-right + + # Offset from the origin + offset = 30x30 + + # Scale factor. It is auto-detected if value is 0. + scale = 0 + + # Maximum number of notifications (0 means no limit) + notification_limit = 0 + + ### Progress bar ### + + # Turn on the progress bar. It appears when a progress hint is passed + # with for example dunstify -h int:value:12 + progress_bar = true + + # Set the progress bar height. This includes the frame, so make sure + # it's at least twice as big as the frame width. + progress_bar_height = 30 + + # Set the frame width of the progress bar + progress_bar_frame_width = 1 + + # Set the minimum width for the progress bar + progress_bar_min_width = 150 + + # Set the maximum width for the progress bar + progress_bar_max_width = 300 + + # Show how many messages are currently hidden (because of + # notification_limit). + indicate_hidden = yes + + # The transparency of the window. Range: [0; 100]. + # This option will only work if a compositing window manager is + # present (e.g. xcompmgr, compiz, picom, etc.). (X11 only) + transparency = 20 + + # Draw a line of "separator_height" pixel height between two + # notifications. Set to 0 to disable. + separator_height = 2 + + # Padding between text and separator. + padding = 10 + + # Horizontal padding + horizontal_padding = 10 + + # Padding between text and icon. + text_icon_padding = 0 + + # Defines width in pixels of fram around the notification window. + # Set to 0 to disable. + frame_width = 3 + + # Defines color of the frame around the notification window + frame_color = "#aaaaaa" + + # Define a color for the separator. + # possible values are: + # * auto: dunst tries to find a color fitting to the background; + # * foreground: use the same color as the foreground; + # * frame: use the same color as the frame; + # * anything else will be interpreted as a X color. + separator_color = frame + + # Sort messages by urgency. + sort = yes + + # Don't remove messages if the user is idle (no mouse/keyboard input) + # for longer than idle_threshold seconds (0 to disable) + # A client can set the 'transient' hint to bypass this. See the rules + # section for how to disable this if necessary + idle_threshold = 120 + + ### Text ### + font = JetBrains Mono 11 + + # The spacing between the lines. If the height is smaller than the + # font height, it will get raised to the font height. + line_height = 0 + + # Possible values are: + # full: Allow a small subset of html markup in notifications: + # bold + # italic + # strikethrough + # underline + # + # For a complete reference see + # . + # + # strip: This setting is provided for compatibility with some broken + # clients that send markup even though it's not enabled on the + # server. Dunst will try to strip the markup but the parsing is + # simplistic so using this option outside of matching rules for + # specific applications *IS GREATLY DISCOURAGED*. + # + # no: Disable markup parsing, incoming notifications will be treated as + # plain text. Dunst will not advertise that it has the body-markup + # capability if this is set as a global setting. + # + # It's important to note that markup inside the format option will be parsed + # regardless of what this is set to. + markup = full + + # The format of the message. Possible variables are: + # %a appname + # %s summary + # %b body + # %i iconname (including its path) + # %I iconname (without its path) + # %p progress value if set ([ 0%] to [100%]) or nothing + # %n progress value if set without any extra characters + # %% Literal % + # Markup is allowed + format = "%a - %s\n%b" + + # Alignment of the message text. + # Possible values are "left", "center" and "right". + alignment = left + + # Vertical alignment of message text and icon. + # Possible values are "top", "center" and "bottom". + vertical_alignment = center + + # Wrap longer sentences which don't fit into the horizonal size + # of the noticication. If set to no, longer sententences will be truncated + word_wrap = yes + + # Specify where to make an ellipsis in the long lines. + # Possible values are "start", "middle", "end". + ellipsize = middle + + # Ignore newlines '\n' in notifications. + ignore_newline = no + + # Show age of message if message is older than show_age_threshold seconds + # Set to -1 to disable, 0 to always show. + show_age_threshold = 60 + + # Merge multiple notifications with the same content + stack_duplicates = true + + # Hide the count of merged notifications with the same content + hide_duplicate_count = false + + # Display indicators for URLs (U) and actions (A) + show_indicators = yes + + ### Icons ### + + # Align icons left/right/off + icon_position = left + + # Scale small icons up to this size, set to 0 to disable. Helpful + # for e.g. small files or high-dpi screens. In case of conflict, + # max_icon_size takes precedence over this. + min_icon_size = 0 + + # Scale larger icons down to this size, set to 0 to disable + max_icon_size = 32 + + # Paths to default icons + icon_path = /usr/share/icons/hicolor/16x16/status/:/usr/share/icons/hicolor/16x16/devices/:/usr/share/icons/hicolor/16x16/apps/ + + ### History ### + + # Should a notification popped up from history be sticky or timeout + # as if it would normally do. + sticky_history = yes + + # Maximum amount of notifications kept in history + history_length = 20 + + ### Misc/Advanced ### + + # dmenu path + dmenu = /usr/local/bin/dmenu -p dunst: + + # Browser for opening urls in content menu + browser = /usr/bin/xdg-open + + # Always run rule-defined scripts, even if the notification is suppressed + always_run_script = true + + # Define the title of the windows spawned by dunst + title = Dunst + + # Define the class of the windows spawned by dunst + class = Dunst + + # Define the corner radius of the notification window + # in pixel size. If the radius is 0, you have no rounded + # corners. + # The radius will be automatically lowered if it exceeds half of the + # notification height to avoid clipping text and/or icons. + corner_radius = 0 + + # Ignore the dbus closeNotification message. + # Useful to enforce the timeout set by dunst configuration. Without this + # parameter, an application may close the notification sent before the + # user defined timeout. + ignore_dbusclose = false + + ### Wayland ### + # These settings are Wayland-specific. They have no effect when using X11 + + # Uncomment this if you want to let notications appear under fullscreen + # applications (default: overlay) + # layer = top + + # Set this to true to use X11 output on Wayland. + force_xwayland = false + + ### Legacy ### + + # Use the Xinerama extension instead of RandR for multi-monitor support. + # This setting is provided for compatibility with older nVidia drivers that + # do not support RandR and using it on systems that support RandR is highly + # discouraged. + # + # By enabling this setting dunst will not be able to detect when a monitor + # is connected or disconnected which might break follow mode if the screen + # layout changes. + force_xinerama = false + + ### Mouse ### + + # Defines list of actions for each mouse event + # Possible values are: + # * none: Don't do anything. + # * do_action: Invoke the action determined by the action_name rule. If there is no + # such action, open the context menu. + # * open_url: If the notification has exactly one url, open it. If there are multiple + # ones, open the context menu. + # * close_current: Close current notification. + # * close_all: Close all notifications. + # * context: Open context menu for the notification. + # * context_all: Open context menu for all notifications. + # These values can be strung together for each mouse event, and + # will be executed in sequence. + mouse_left_click = do_action, open_url, close_current + mouse_middle_click = context + mouse_right_click = close_current + +# Experimental features that may or may not work correctly. Do not expect them +# to have a consistent behaviour across releases. +[experimental] + # Calculate the dpi to use on a per-monitor basis. + # If this setting is enabled the Xft.dpi value will be ignored and instead + # dunst will attempt to calculate an appropriate dpi value for each monitor + # using the resolution and physical size. This might be useful in setups + # where there are multiple screens with very different dpi values. + per_monitor_dpi = false + +[urgency_low] + highlight = "#fe6c5a" + background = "#1e2137fa" + frame_color = "#27292c" + foreground = "#ffffff" + + timeout = 5 + # Icon for notifications with low urgency, uncomment to enable + #icon = /path/to/icon + +[urgency_normal] + highlight = "#fe6c5a" + background = "#141c21fa" + frame_color = "#27292c" + foreground = "#ffffffff" + + timeout = 10 + # Icon for notifications with normal urgency, uncomment to enable + #icon = /path/to/icon + +[urgency_critical] + highlight = "#fe6c5a" + background = "#dd130ddd" + frame_color = "#27292c" + foreground = "#ffffffff" + + timeout = 0 + icon = arbt + # Icon for notifications with critical urgency, uncomment to enable + #icon = /path/to/icon + + +# Every section that isn't one of the above is interpreted as a rules to +# override settings for certain messages. +# +# Messages can be matched by +# appname (discouraged, see desktop_entry) +# body +# category +# desktop_entry +# icon +# match_transient +# msg_urgency +# stack_tag +# summary +# +# and you can override the +# background +# foreground +# format +# frame_color +# fullscreen +# new_icon +# set_stack_tag +# set_transient +# set_category +# timeout +# urgency +# icon_position +# skip_display +# history_ignore +# action_name +# word_wrap +# ellipsize +# alignment +# hide_text +# +# Shell-like globbing will get expanded. +# +# Instead of the appname filter, it's recommended to use the desktop_entry filter. +# GLib based applications export their desktop-entry name. In comparison to the appname, +# the desktop-entry won't get localized. +# +# SCRIPTING +# You can specify a script that gets run when the rule matches by +# setting the "script" option. +# The script will be called as follows: +# script appname summary body icon urgency +# where urgency can be "LOW", "NORMAL" or "CRITICAL". +# +# NOTE: It might be helpful to run dunst -print in a terminal in order +# to find fitting options for rules. + +# Disable the transient hint so that idle_threshold cannot be bypassed from the +# client +#[transient_disable] +# match_transient = yes +# set_transient = no +# +# Make the handling of transient notifications more strict by making them not +# be placed in history. +#[transient_history_ignore] +# match_transient = yes +# history_ignore = yes + +# fullscreen values +# show: show the notifications, regardless if there is a fullscreen window opened +# delay: displays the new notification, if there is no fullscreen window active +# If the notification is already drawn, it won't get undrawn. +# pushback: same as delay, but when switching into fullscreen, the notification will get +# withdrawn from screen again and will get delayed like a new notification +#[fullscreen_delay_everything] +# fullscreen = delay +#[fullscreen_show_critical] +# msg_urgency = critical +# fullscreen = show + +#[espeak] +# summary = "*" +# script = dunst_espeak.sh + +#[script-test] +# summary = "*script*" +# script = dunst_test.sh + +#[ignore] +# # This notification will not be displayed +# summary = "foobar" +# skip_display = true + +#[history-ignore] +# # This notification will not be saved in history +# summary = "foobar" +# history_ignore = yes + +#[skip-display] +# # This notification will not be displayed, but will be included in the history +# summary = "foobar" +# skip_display = yes + +#[signed_on] +# appname = Pidgin +# summary = "*signed on*" +# urgency = low +# +#[signed_off] +# appname = Pidgin +# summary = *signed off* +# urgency = low +# +#[says] +# appname = Pidgin +# summary = *says* +# urgency = critical +# +#[twitter] +# appname = Pidgin +# summary = *twitter.com* +# urgency = normal +# +#[stack-volumes] +# appname = "some_volume_notifiers" +# set_stack_tag = "volume" +# +# vim: ft=cfg diff --git a/home/.config/eww/css/_colors.scss b/home/.config/eww/css/_colors.scss new file mode 100644 index 0000000..1534b69 --- /dev/null +++ b/home/.config/eww/css/_colors.scss @@ -0,0 +1,43 @@ +$rosewater: #f5e0dc; +$flamingo: #f2cdcd; +$pink: #f5c2e7; +$mauve: #cba6f7; +$red: #f38ba8; +$maroon: #eba0ac; +$peach: #fab387; +$yellow: #f9e2af; +$gold: #efcb10; +$green: #a6e3a1; +$lime: #78db32; +$teal: #94e2d5; +$sky: #89dceb; +$sapphire: #74c7ec; +$blue: #89b4fa; +$lavender: #b4befe; +$orange: #ffa500; + +$text: #cdd6f4; +$subtext1: #bac2de; +$subtext0: #a6adc8; +$overlay2: #9399b2; +$overlay1: #7f849c; +$overlay0: #6c7086; + +$surface2: #585b70; +$surface1: #45475a; +$surface0: #313244; + +$base-a: rgba(30, 30, 40, 0.65); +$base: rgba(30, 30, 40, 1); +$base1-a: rgba(49, 50, 68, 0.85); +$base1: rgba(49, 50, 68, 1); +$mantle: #181825; +$crust: #11111b; + +$fg: $text; +$bg-a: $base-a; +$bg: $base; +$bg1: $base1; +$bg1-a: $base1-a; +$border: #28283d; +$shadow: $crust; diff --git a/home/.config/eww/css/modules/_battery.scss b/home/.config/eww/css/modules/_battery.scss new file mode 100644 index 0000000..43f1062 --- /dev/null +++ b/home/.config/eww/css/modules/_battery.scss @@ -0,0 +1,46 @@ +@keyframes blink { + 0%{ + opacity: 0; + } + 50%{ + opacity: 0.7; + } + 100%{ + opacity: 0; + } + } + +// .unplugged.low { +// color: #0000ff; +// } + +.battery { + .critical { + .unplugged { + color: #f00; + .extra { animation: blink 1.2s linear infinite; } + } + + .plugged { + .icon { color: $orange } + .extra { color: $green; } + } + } + + .normal { + .unplugged { + .icon { color: $orange } + } + .plugged { + .icon { color: $green; } + } + } + + .full { + .icon { color: $green; } + .extra { color: $lime; } + } + + .extra { margin-right: 5px; } + .icon { margin-right: 5px; } +} diff --git a/home/.config/eww/css/modules/_bitcoin.scss b/home/.config/eww/css/modules/_bitcoin.scss new file mode 100644 index 0000000..82d5a61 --- /dev/null +++ b/home/.config/eww/css/modules/_bitcoin.scss @@ -0,0 +1,3 @@ +.bitcoin { + .icon { margin-right: 6px; color: $gold; } +} diff --git a/home/.config/eww/css/modules/_clock.scss b/home/.config/eww/css/modules/_clock.scss new file mode 100644 index 0000000..98d9823 --- /dev/null +++ b/home/.config/eww/css/modules/_clock.scss @@ -0,0 +1,4 @@ +.clock { + // color: $sapphire; + .icon { margin-right: 6px; color: $sapphire; } +} diff --git a/home/.config/eww/css/modules/_cpu.scss b/home/.config/eww/css/modules/_cpu.scss new file mode 100644 index 0000000..a183c58 --- /dev/null +++ b/home/.config/eww/css/modules/_cpu.scss @@ -0,0 +1,3 @@ +.cpu { + .icon { color: $lime; } +} diff --git a/home/.config/eww/css/modules/_kernel.scss b/home/.config/eww/css/modules/_kernel.scss new file mode 100644 index 0000000..652a60d --- /dev/null +++ b/home/.config/eww/css/modules/_kernel.scss @@ -0,0 +1,3 @@ +.kernel { + .icon { color: $lavender; } +} diff --git a/home/.config/eww/css/modules/_memory.scss b/home/.config/eww/css/modules/_memory.scss new file mode 100644 index 0000000..37d8432 --- /dev/null +++ b/home/.config/eww/css/modules/_memory.scss @@ -0,0 +1,3 @@ +.memory { + .icon { color: $maroon; } +} diff --git a/home/.config/eww/css/modules/_uptime.scss b/home/.config/eww/css/modules/_uptime.scss new file mode 100644 index 0000000..63b1353 --- /dev/null +++ b/home/.config/eww/css/modules/_uptime.scss @@ -0,0 +1,3 @@ +.uptime { + .icon { color: $green; } +} diff --git a/home/.config/eww/css/modules/_volume.scss b/home/.config/eww/css/modules/_volume.scss new file mode 100644 index 0000000..7a94630 --- /dev/null +++ b/home/.config/eww/css/modules/_volume.scss @@ -0,0 +1,9 @@ +.volume { + .icon { color: $peach; } + .speaker { + .icon { + margin-left: 8px; + margin-right: 5px; + } + } +} diff --git a/home/.config/eww/css/modules/_workspaces.scss b/home/.config/eww/css/modules/_workspaces.scss new file mode 100644 index 0000000..040ad77 --- /dev/null +++ b/home/.config/eww/css/modules/_workspaces.scss @@ -0,0 +1,26 @@ +.workspaces { + background-color: $bg1-a; + border-radius: 25px; + + .value { + margin-left: 10px; + margin-right: 10px; + } + + .focused { + // text-decoration: underline; + // text-decoration-color: red; + // text-decoration-style: double; + font-weight: 900; + // color: $sapphire; + color: #fff; + } + + .active { + color: #bbb; + } + + .inactive { + color: #555; + } +} diff --git a/home/.config/eww/css/windows/_calendar.scss b/home/.config/eww/css/windows/_calendar.scss new file mode 100644 index 0000000..2aadfa3 --- /dev/null +++ b/home/.config/eww/css/windows/_calendar.scss @@ -0,0 +1,32 @@ +.calendar-win { + @include window; + background-color: $bg; + border: 1px solid $border; + color: $fg; + padding: .2em; +} + +calendar { + padding: 5px; + + :selected { + color: $mauve; + } + + .header { + color: $subtext1; + } + + .highlight { + color: $maroon; + font-weight: bold; + } + + .button { + color: $sapphire; + } + + :indeterminate { + color: $overlay0; + } +} diff --git a/home/.config/eww/eww.scss b/home/.config/eww/eww.scss new file mode 100644 index 0000000..18be4bf --- /dev/null +++ b/home/.config/eww/eww.scss @@ -0,0 +1,71 @@ +@import 'css/colors'; + +@mixin rounding { + border-radius: 16px; +} + +@mixin window { + border: 1px solid $border; + box-shadow: 0 2px 3px $shadow; + margin: 5px 5px 10px; + @include rounding; +} + +* { + all: unset; + transition: 200ms ease; +} + +@import "css/windows/calendar"; +@import "css/modules/clock"; +@import "css/modules/volume"; +@import "css/modules/bitcoin"; +@import "css/modules/cpu"; +@import "css/modules/memory"; +@import "css/modules/uptime"; +@import "css/modules/kernel"; +@import "css/modules/battery"; +@import "css/modules/workspaces"; + +.bar { + background-color: $bg-a; + color: $fg; + + font-family: "JetBrains Mono", "Font Awesome 6 Free"; + // margin-right: 10px; + + label { + font-size: 14px; + } + + // TODO: Use ercentages (for some reason it fails now) + min-width: 1920px; + padding-right: 20px; + padding-left: 20px; +} + +tooltip { + background: $bg; + border: 1px solid $border; + border-radius: 8px; + + label { + font-size: 1rem; + } +} + +.module { margin: 0 5px; } + +.separ { + color: $surface0; + font-size: 1.5rem; + padding-bottom: 2px; +} + +scale trough { + background-color: $bg1-a; + border-radius: 24px; + margin: 0 1rem; + min-height: 10px; + min-width: 70px; +} diff --git a/home/.config/eww/eww.yuck b/home/.config/eww/eww.yuck new file mode 100644 index 0000000..16d1b04 --- /dev/null +++ b/home/.config/eww/eww.yuck @@ -0,0 +1,73 @@ +(defvar terminal "alacritty -e") + +(include "./modules/clock.yuck") +(include "./modules/volume.yuck") +(include "./modules/bitcoin.yuck") +(include "./modules/cpu.yuck") +(include "./modules/memory.yuck") +(include "./modules/uptime.yuck") +; (include "./modules/kernel.yuck") +(include "./modules/battery.yuck") +(include "./modules/window_name.yuck") +(include "./modules/workspaces.yuck") + +(include "./windows/calendar.yuck") + +(defwidget sep [] + (label :class "separ module" :text "|")) + +(defwidget left [] + (box + :space-evenly false + :halign "start" + (window_name_module) + )) + +(defwidget right [] + (box + :space-evenly false + :halign "end" + ; (kernel_module) + ; (sep) + (volume_module) + (sep) + (battery_module) + (sep) + (bitcoin_module) + (sep) + (cpu_module) + (sep) + (memory_module) + (sep) + (uptime_module) + (sep) + (clock_module) + (sep) + (system-tray) + )) + +(defwidget center [] + (box + :space-evenly false + :halign "center" + (workspaces_module) + )) + +(defwidget bar [] + (centerbox + :class "bar" + :orientation "horizontal" + (left) + (center) + (right))) + +(defwindow bar + :monitor 0 + :geometry (geometry :x "0%" + :y "0%" + :width: "100%" + :height "32px" + :anchor "top center") + :stacking "fg" + :exclusive true + (bar)) diff --git a/home/.config/eww/modules/battery.yuck b/home/.config/eww/modules/battery.yuck new file mode 100644 index 0000000..c8f194b --- /dev/null +++ b/home/.config/eww/modules/battery.yuck @@ -0,0 +1,29 @@ +(defpoll battery + :interval "2s" + :initial '{"percent":"0","plugged":"false","status":"N/A","capacity_icon":"","extra_icon":"","manufacturer":"N/A","model_name":"N/A","technology":"N/A","energy_now":"0","enerfy_full":"0","enerfy_full_design":"0","cycle_count":"0","critical":"false","full":"false"}' + `scripts/battery`) + +(defwidget battery_module [] + (eventbox + :class "module battery" + + (box + :class {battery.critical ? "critical" : battery.full ? "full" : "normal"} + (box + :space-evenly false + :class {battery.plugged ? "plugged" : "unplugged" } + + (box + :class "icon" + :space-evenly false + + (label + :class "extra" + :text {battery.extra_icon}) + (label + :text {battery.capacity_icon})) + (label + :class "value" + :text "${battery.percent}%" + ) + )))) diff --git a/home/.config/eww/modules/bitcoin.yuck b/home/.config/eww/modules/bitcoin.yuck new file mode 100644 index 0000000..6e5039e --- /dev/null +++ b/home/.config/eww/modules/bitcoin.yuck @@ -0,0 +1,19 @@ +(defpoll bitcoin + :interval "5m" + :initial "$N/A" + `~/.local/bin/scripts/cli/bitcoin`) + +(defwidget bitcoin_module [] + (eventbox + :onclick "~/.local/bin/scripts/cli/bitcoin | xargs -I_ ${EWW_CMD} update bitcoin=_" + :class "module bitcoin" + + (box + :space-evenly false + + (label + :class "icon" + :text "ﴑ") + (label :text {bitcoin})) + ) +) diff --git a/home/.config/eww/modules/clock.yuck b/home/.config/eww/modules/clock.yuck new file mode 100644 index 0000000..5a73b50 --- /dev/null +++ b/home/.config/eww/modules/clock.yuck @@ -0,0 +1,22 @@ +(defpoll time + :interval "5s" + :initial '{"date": "01 Jan", "hour": "00", "minute": "00", "day": "Monday"}' + `date +'{"date": "%d %b", "hour": "%H", "minute": "%M", "day": "%A"}'`) + +(defwidget clock_module [] + + (eventbox + :onclick "${EWW_CMD} open --toggle calendar" + :tooltip {time.day} + :class "module clock" + + (box + :space-evenly false + + (label + :class "icon" + :text "") + (label + :class "value" + :text "${time.date} ${time.hour}:${time.minute}")) + )) diff --git a/home/.config/eww/modules/cpu.yuck b/home/.config/eww/modules/cpu.yuck new file mode 100644 index 0000000..940ffb3 --- /dev/null +++ b/home/.config/eww/modules/cpu.yuck @@ -0,0 +1,15 @@ +(defwidget cpu_module [] + (eventbox + :class "module cpu" + + (box + :space-evenly false + + (label + :class "icon" + :text " ") + (label + :class "value" + :text "${round(EWW_CPU.avg,2)}%" + ) + ))) diff --git a/home/.config/eww/modules/kernel.yuck b/home/.config/eww/modules/kernel.yuck new file mode 100644 index 0000000..b0561d4 --- /dev/null +++ b/home/.config/eww/modules/kernel.yuck @@ -0,0 +1,23 @@ +; TODO: Figure out how to store this one-time + +(defpoll kernel + :interval "10000h" + :initial 'N/A' + ; `uname -r | sed -r 's/(.+)-arch(.+)/\\1/'` + `uname -r`) + +(defwidget kernel_module [] + (eventbox + :class "module kernel" + + (box + :space-evenly false + + (label + :class "icon" + :text " ") + (label + :class "value" + :text {kernel} + ) + ))) diff --git a/home/.config/eww/modules/memory.yuck b/home/.config/eww/modules/memory.yuck new file mode 100644 index 0000000..7c33074 --- /dev/null +++ b/home/.config/eww/modules/memory.yuck @@ -0,0 +1,15 @@ +(defwidget memory_module [] + (eventbox + :class "module memory" + + (box + :space-evenly false + + (label + :class "icon" + :text " ") + (label + :class "value" + :text "${round(EWW_RAM.used_mem / 1000000,1)}G: ${round(EWW_RAM.used_mem_perc,0)}%" + ) + ))) diff --git a/home/.config/eww/modules/nightlight.yuck b/home/.config/eww/modules/nightlight.yuck new file mode 100644 index 0000000..fd2f2fe --- /dev/null +++ b/home/.config/eww/modules/nightlight.yuck @@ -0,0 +1,3 @@ +(deflisten nightlight + :initial `{"running": false,"temperature": 0}` + `scripts/nightlight --state`) diff --git a/home/.config/eww/modules/uptime.yuck b/home/.config/eww/modules/uptime.yuck new file mode 100644 index 0000000..d05a306 --- /dev/null +++ b/home/.config/eww/modules/uptime.yuck @@ -0,0 +1,29 @@ +(defpoll uptime + :interval "1m" + :initial 'N/A' + `uptime -p | sed \\ + -e 's/^up //' \\ + -e 's/ years\\?,\\?/y/' \\ + -e 's/ months\\?,\\?/m/' \\ + -e 's/ weeks\\?,\\?/w/' \\ + -e 's/ days\\?,\\?/d/' \\ + -e 's/ hours\\?,\\?/h/' \\ + -e 's/ minutes\\?,\\?/m/' \\ + -e 's/ seconds\\?,\\?/s/' \\ + | cut -d' ' -f-2`) + +(defwidget uptime_module [] + (eventbox + :class "module uptime" + + (box + :space-evenly false + + (label + :class "icon" + :text " ") + (label + :class "value" + :text {uptime} + ) + ))) diff --git a/home/.config/eww/modules/volume.yuck b/home/.config/eww/modules/volume.yuck new file mode 100644 index 0000000..44b3496 --- /dev/null +++ b/home/.config/eww/modules/volume.yuck @@ -0,0 +1,44 @@ +(defvar mic_rev false) + +(deflisten volume + :initial '{ "speaker_vol": "100", "speaker_mute": false, "speaker_icon": "", "microphone_mute": false, "microphone_vol": "100", "microphone_icon": "" }' + `scripts/volume loop`) + +(defwidget volume_module [] + (box + :class "module volume" + :space-evenly false + + (eventbox + :onscroll "scripts/volume setvol SOURCE 0.5 {}" + :onclick "scripts/volume togglemute SOURCE" + :onrightclick "${terminal} pulsemixer &" + :onhover "${EWW_CMD} update mic_rev=true" + :onhoverlost "${EWW_CMD} update mic_rev=false" + :class "microphone" + (box + (label + :class "icon" + :text {volume.microphone_icon}) + (label + :visible {mic_rev && !volume.microphone_mute} + :class "value" + :text "${volume.microphone_vol}%") + )) + + (eventbox + :onscroll "scripts/volume setvol SINK 0.5 {}" + :onclick "scripts/volume togglemute SINK" + :onrightclick "${terminal} pulsemixer &" + :class "speaker" + (box + (label + :class "icon" + :text {volume.speaker_icon}) + (label + :visible {!volume.speaker_mute} + :class "value" + :text "${volume.speaker_vol}%") + )) + + )) diff --git a/home/.config/eww/modules/window_name.yuck b/home/.config/eww/modules/window_name.yuck new file mode 100644 index 0000000..af74d58 --- /dev/null +++ b/home/.config/eww/modules/window_name.yuck @@ -0,0 +1,15 @@ +(deflisten window_name + :initial `{"class":"","name":"","formatted_name":""}` + `scripts/window_name`) + +; Consider making the window name clickable, opening up a full window that's showing +; the selected window details (class, unformatted name, and perhaps even more, like +; xwayland status, ...) +(defwidget window_name_module [] + (box + :class "module window_name" + + (label + :class "value" + :text "${window_name.formatted_name}") + )) diff --git a/home/.config/eww/modules/workspaces.yuck b/home/.config/eww/modules/workspaces.yuck new file mode 100644 index 0000000..cfbaf66 --- /dev/null +++ b/home/.config/eww/modules/workspaces.yuck @@ -0,0 +1,26 @@ +(deflisten workspaces + :initial `[{"id": 1,"name": "N/A","monitor": "N/A","windows": 1,"hasfullscreen": false,"lastwindow": "N/A","lastwindowtitle": "N/A","format_name": "N/A","active": true}]` + `scripts/workspaces --loop`) + + +; (defwidget sep [] +; (label :class "separ module" :text "|")) + + +; Consider making the window name clickable, opening up a full window that's showing +; the selected window details (class, unformatted name, and perhaps even more, like +; xwayland status, ...) +(defwidget workspaces_module [] + (box + :class "module workspaces" + + (for workspace in workspaces + (eventbox + :class {workspace.active ? 'focused' : workspace.windows > 0 ? 'active' : 'inactive'} + :onclick `scripts/workspaces --switch ${workspace.id}` + + (label + :class "value" + :text {workspace.format_name})) + ) + )) diff --git a/home/.config/eww/scripts/.flake8 b/home/.config/eww/scripts/.flake8 new file mode 100644 index 0000000..ce90fbd --- /dev/null +++ b/home/.config/eww/scripts/.flake8 @@ -0,0 +1,11 @@ +[flake8] +max-line-length=119 +extend-ignore=E203 +extend-select=B902,B904 +exclude=.venv,.git,.cache +ignore= + ANN002, # *args annotation + ANN003, # **kwargs annotation + ANN101, # self param annotation + ANN102, # cls param annotation + ANN204, # return type annotation for special methods diff --git a/home/.config/eww/scripts/battery b/home/.config/eww/scripts/battery new file mode 100755 index 0000000..3395c82 --- /dev/null +++ b/home/.config/eww/scripts/battery @@ -0,0 +1,79 @@ +#!/bin/bash + +# shellcheck source=include +source "./scripts/include" + +# $BATTERY and $ADAPTER env vars can be set manually, being the names of the +# devices (in /sys/class/power_supply/) i.e. BATTERY=BAT0 ADAPTER=ADP0 +# or, if left unset, they will be automatically picked. + +CAPACITY_ICONS=("" "" "" "" "") +CHARGING_ICON="" +DISCHARGING_ICON="" +FULL_ICON="" # Plugged in, but no longer charging (fully charged) +CRITICAL_ICON="" +CRITICAL_PERCENTAGE=15 + + +if [ -z "$BATTERY" ]; then + # shellcheck disable=SC2010 + BATTERY="$(ls -t /sys/class/power_supply | grep "BAT" | head -n 1)" +fi + +if [ -z "$ADAPTER" ]; then + # shellcheck disable=SC2010 + ADAPTER="$(ls -t /sys/class/power_supply | grep "ADP" | head -n 1)" +fi + +get_bat_info() { + cat /sys/class/power_supply/"$BATTERY"/"$1" +} + +get_adp_info() { + cat /sys/class/power_supply/"$ADAPTER"/"$1" +} + +manufacturer="$(get_bat_info manufacturer)" +model_name="$(get_bat_info model_name)" +technology="$(get_bat_info technology)" +energy_now="$(get_bat_info energy_now)" +energy_full="$(get_bat_info energy_full)" +energy_full_design="$(get_bat_info energy_full_design)" +cycle_count="$(get_bat_info cycle_count)" + +capacity="$(get_bat_info capacity)" +status="$(get_bat_info status)" +[ "$(get_adp_info online)" -eq 1 ] && adp_connected="true" || adp_connected="false" + +full="false" +capacity_icon="$(pick_icon "$capacity" 0 100 "${CAPACITY_ICONS[@]}")" + +if [ "$status" = "Not charging" ] || [ "$status" = "Full" ] && [ "$adp_connected" = "true" ]; then + extra_icon="$FULL_ICON" + full="true" +elif [ "$status" = "Discharging" ] && [ "$capacity" -le "$CRITICAL_PERCENTAGE" ]; then + extra_icon="$CRITICAL_ICON" +elif [ "$status" = "Discharging" ]; then + extra_icon="$DISCHARGING_ICON" +elif [ "$status" = "Charging" ]; then + extra_icon="$CHARGING_ICON" +fi + +[ "$capacity" -le "$CRITICAL_PERCENTAGE" ] && critical="true" || critical="false" + +jq -n -c --monochrome-output \ + --arg percent "$capacity" \ + --arg plugged "$adp_connected" \ + --arg status "$status" \ + --arg capacity_icon "$capacity_icon" \ + --arg extra_icon "$extra_icon" \ + --arg manufacturer "$manufacturer" \ + --arg model_name "$model_name" \ + --arg technology "$technology" \ + --arg energy_now "$energy_now" \ + --arg energy_full "$energy_full" \ + --arg energy_full_design "$energy_full_design" \ + --arg cycle_count "$cycle_count" \ + --arg critical "$critical" \ + --arg full "$full" \ + '$ARGS.named' diff --git a/home/.config/eww/scripts/include b/home/.config/eww/scripts/include new file mode 100755 index 0000000..34b5b99 --- /dev/null +++ b/home/.config/eww/scripts/include @@ -0,0 +1,49 @@ +#!/bin/bash + +# $1: Current number +# $2: Range minimum +# $3: Range maximum +# $4-: Icons as individual arguments +pick_icon() { + cur="$1" + min="$2" + max="$3" + shift 3 + icons=( "$@" ) + + index="$(echo "($cur-$min)/(($max-$min)/${#icons[@]})" | bc)" + + # Print the picked icon, handling overflows/underflows, i.e. if our index is <0 or >len(icons) + if [ "$index" -ge "${#icons[@]}" ]; then + index=-1 + elif [ "$index" -lt 0 ]; then + index=0 + fi + + echo "${icons[index]}" +} + +# Will block and listen to the hyprland socket messages and output them +# Generally used like: hyprland_ipc | while read line; do handle $line; done +# Read for output format and available events +# Note: requires openbsd version of netcat. +# $1 - Optional event to listen for (no event filtering will be done if not provided) +hyprland_ipc() { + if [ -z "$HYPRLAND_INSTANCE_SIGNATURE" ]; then + >&2 echo "Hyprland is not running, IPC not available" + exit 1 + fi + + SOCKET_PATH="/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" + + if [ -z "$1" ]; then + nc -U "$SOCKET_PATH" | while read -r test; do + echo "$test" + done + else + nc -U "$SOCKET_PATH" | while read -r test; do + # shellcheck disable=SC2016 + echo "$test" | grep --line-buffered -E "^$1>>" | stdbuf -oL awk -F '>>' '{print $2}' + done + fi +} diff --git a/home/.config/eww/scripts/nightlight b/home/.config/eww/scripts/nightlight new file mode 100644 index 0000000..f8e4c24 --- /dev/null +++ b/home/.config/eww/scripts/nightlight @@ -0,0 +1,13 @@ +#!/bin/bash + +# shellcheck source=include +source "./scripts/include" + +# Consider usning a file as a flag for whether nightlight is on or off +# as we might be in transition state and just killing the program might +# not be enough. + + +if [ "$1" = "toggle" ]; then + gammastep -x +fi diff --git a/home/.config/eww/scripts/pyproject.toml b/home/.config/eww/scripts/pyproject.toml new file mode 100644 index 0000000..e3a2d4f --- /dev/null +++ b/home/.config/eww/scripts/pyproject.toml @@ -0,0 +1,12 @@ +[tool.black] +line-length = 119 +extend-exclude = "^/.cache" + +[tool.isort] +profile = "black" +line_length = 119 +atomic = true +order_by_type = false +case_sensitive = true +combine_as_imports = true +skip = [".venv", ".git", ".cache"] diff --git a/home/.config/eww/scripts/storage b/home/.config/eww/scripts/storage new file mode 100755 index 0000000..210e71c --- /dev/null +++ b/home/.config/eww/scripts/storage @@ -0,0 +1,35 @@ +#!/bin/bash + +MOUNTPOINTS=("/" "/mnt/ext") + +data="$(df -H)" + +as_json() { + mountpoint="$1" + res="$2" + arr_res=($res) + + jq -n -c --monochrome-output \ + --arg mountpoint "$mountpoint" \ + --arg size "${arr_res[0]}" \ + --arg used "${arr_res[1]}" \ + --arg avail "${arr_res[2]}" \ + --arg percent "${arr_res[3]}" \ + '$ARGS.named' +} + +output_json="[]" +for mountpoint in "${MOUNTPOINTS[@]}"; do + res="$(echo "$data" | awk -v m="$mountpoint" '$6 == m {print $2 " " $3 " " $4 " " $5}')" + out="$(as_json "$mountpoint" "$res")" + + # echo "$output_json $out" | jq -c -s + + jq --argjson arr1 "$output_json" --argjson arr2 "[$out]" -n \ +'$arr1 + $arr2' + + # mount_data+=("$mountpoint" $res) + # echo "${mount_data[@]}" +done + +# echo "${mount_data[@]}" diff --git a/home/.config/eww/scripts/temp b/home/.config/eww/scripts/temp new file mode 100755 index 0000000..66262de --- /dev/null +++ b/home/.config/eww/scripts/temp @@ -0,0 +1,6 @@ +#!/bin/bash + +# shellcheck source=include +source "./scripts/include" + +hyprland_ipc "workspace|createworkspace|destroyworkspace" diff --git a/home/.config/eww/scripts/volume b/home/.config/eww/scripts/volume new file mode 100755 index 0000000..5d9b850 --- /dev/null +++ b/home/.config/eww/scripts/volume @@ -0,0 +1,114 @@ +#!/bin/bash + +# Define some icons +SPEAKER_ICONS=("" "" "") +SPEAKER_MUTED_ICON="" +MIC_ICON="" +MIC_MUTED_ICON="" + +# Define some helper functions for getting/setting audio data using wireplumber (wpctl) + +# $1 can either be "SINK" (speaker) or "SOURCE" (microphone) +get_vol() { + wpctl get-volume "@DEFAULT_AUDIO_${1}@" | awk '{print int($2*100)}' +} + +# $1 can either be "SINK" (speaker) or "SOURCE" (microphone) +# #2 is the voulme (as percentage) to set the volume to +# $3 is optional, if set, it can be '+' or '-', which then adds/decreases volume, instead of setting +set_vol() { + wpctl set-volume "@DEFAULT_AUDIO_${1}@" "$(awk -v n="$2" 'BEGIN{print (n / 100)}')$3" +} + +# $1 can either be "SINK" (speaker) or "SOURCE" (microphone) +check_mute() { + wpctl get-volume "@DEFAULT_AUDIO_${1}@" | grep -i muted >/dev/null + echo $? +} + +# $1 can either be "SINK" (speaker) or "SOURCE" (microphone) +toggle_mute() { + wpctl set-mute "@DEFAULT_AUDIO_${1}@" toggle +} + +get_report() { + spkr_vol="$(get_vol "SINK")" + mic_vol="$(get_vol "SOURCE")" + + if [ "$(check_mute "SINK")" == "0" ]; then + spkr_mute="true" + spkr_icon="$SPEAKER_MUTED_ICON" + else + spkr_mute="false" + index="$(awk -v n="$spkr_vol" -v m="${#SPEAKER_ICONS[@]}" 'BEGIN{print int(n/(100/m))}')" + + # We might end up with an higher than the length of icons, if the volume is over 100% + # in this case, set the index to last icon + if [ "$index" -ge "${#SPEAKER_ICONS[@]}" ]; then + spkr_icon="${SPEAKER_ICONS[-1]}" + else + spkr_icon="${SPEAKER_ICONS[$index]}" + fi + fi + + if [ "$(check_mute "SOURCE")" = "0" ]; then + mic_mute="true" + mic_icon="$MIC_MUTED_ICON" + else + mic_mute="false" + mic_icon="$MIC_ICON" + fi + + echo "{ \"speaker_vol\": \"$spkr_vol\", \"speaker_mute\": $spkr_mute, \"speaker_icon\": \"$spkr_icon\", \"microphone_mute\": $mic_mute, \"microphone_vol\": \"$mic_vol\", \"microphone_icon\": \"$mic_icon\" }" +} + +# Continually run and report every volume change (into stdout) +loop() { + pactl subscribe | grep --line-buffered "change" | while read -r _; do + get_report + done +} + +case "$1" in + "loop") + get_report + loop + ;; + + "once") get_report ;; + + "togglemute") + if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then + >&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'" + exit 1 + fi + toggle_mute "$2" + ;; + + "setvol") + if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then + >&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'" + exit 1 + fi + + if [[ "$3" =~ ^[+-]?[0-9]*\.?[0-9]+$ ]]; then + case "$4" in + "") set_vol "$2" "$3" ;; + up|+) set_vol "$2" "$3" "+" ;; + down|-) set_vol "$2" "$3" "-" ;; + *) + >&2 echo "Invalid usage, expected fourth argument to be up/down or +/-, got '$4'" + exit 1 + ;; + esac + else + >&2 echo "Invalid usage, exepcted third argument to be a number, got '$3'" + exit 1 + fi + ;; + + *) + >&2 echo "Invalid usage, argument '$1' not recognized." + exit 1 + ;; +esac diff --git a/home/.config/eww/scripts/window_name b/home/.config/eww/scripts/window_name new file mode 100755 index 0000000..b828326 --- /dev/null +++ b/home/.config/eww/scripts/window_name @@ -0,0 +1,6 @@ +#!/bin/bash + +# shellcheck source=include +source "./scripts/include" + +hyprland_ipc "activewindow" | ./scripts/window_name.py diff --git a/home/.config/eww/scripts/window_name.py b/home/.config/eww/scripts/window_name.py new file mode 100755 index 0000000..2603b0f --- /dev/null +++ b/home/.config/eww/scripts/window_name.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +"""This is a utility script for regex remaps on window names. + +This is done in python, because of the complex regex logic, which would be pretty hard to +recreate in bash. This python script is expected to be called from the bash script controlling +the window names. Window name and class are obtained from piped stdin, to prevent having to +needlessly keep restarting this program, which takes a while due to the interpreter starting +overhead. +""" +import re +import json +import sys +from typing import Iterator, Optional + + +class RemapRule: + __slots__ = ("name_pattern", "output_pattern", "class_pattern") + + def __init__(self, name_pattern: str, output_pattern: str, class_pattern: Optional[str] = None): + self.name_pattern = re.compile(name_pattern) + self.output_pattern = output_pattern + self.class_pattern = re.compile(class_pattern) if class_pattern else None + + def apply(self, window_name: str, window_class: str) -> str: + """Returns new name after this remap rule was applied.""" + if self.class_pattern is not None: + if not self.class_pattern.fullmatch(window_class): + # Rule doesn't apply, class mismatch, return original name + return window_name + + res = self.name_pattern.fullmatch(window_name) + if not res: + # Rule doesn't apply, name mismatch, return original name + return window_name + + # NOTE: This is potentially unsafe, since output_pattern might be say {0.__class__}, etc. + # meaning this allows arbitrary attribute access, however it doesn't allow running functions + # here. That said, code could still end up being run if there's some descriptor defined, + # and generally I wouldn't trust this in production. However, this code is for my personal + # use here, and all of the output patterns are hard-coded in this file, so in this case, it's + # fine. But if you see this code and you'd like to use it in your production code, maybe don't + return self.output_pattern.format(*res.groups()) + + +# Rules will be applied in specified order +REMAP_RULES: list[RemapRule] = [ + RemapRule(r"", "", ""), + RemapRule(r"(.*) — Mozilla Firefox", " {}", "firefox"), + RemapRule(r"Mozilla Firefox", " Mozilla Firefox", "firefox"), + RemapRule(r"Alacritty", " Alacritty", "Alacritty"), + RemapRule(r"zsh;#toggleterm#1 - \(term:\/\/(.+)\/\/(\d+):(.+)\) - N?VIM", " Terminal: {0}"), + RemapRule(r"(.+) \+ \((.+)\) - N?VIM", " {0} ({1}) [MODIFIED]"), + RemapRule(r"(.+) \((.+)\) - N?VIM", " {0} ({1})"), + RemapRule(r"(?:\[\d+\] )?\*?WebCord - (.+)", " {}", "WebCord"), + RemapRule(r"(.+) - mpv", " {}", "mpv"), + RemapRule(r"Stremio - (.+)", " Stremio - {}", "com.stremio.stremio"), + RemapRule(r"Spotify", " Spotify", "Spotify"), + RemapRule(r"pulsemixer", " Pulsemixer"), + RemapRule(r"(.*)", " {}", "Pcmanfm"), +] + +MAX_LENGTH = 65 + + +def iter_window() -> Iterator[tuple[str, str]]: + """Listen for the window parameters from stdin/pipe, yields (window_name, window_class).""" + for line in sys.stdin: + line = line.removesuffix("\n") + els = line.split(",", maxsplit=1) + if len(els) != 2: + raise ValueError(f"Expected 2 arguments from stdin line (name, class), but got {len(els)}") + yield els[1], els[0] + + +def main() -> None: + for window_name, window_class in iter_window(): + formatted_name = window_name + for remap_rule in REMAP_RULES: + formatted_name = remap_rule.apply(formatted_name, window_class) + + if len(formatted_name) > MAX_LENGTH: + formatted_name = formatted_name[:MAX_LENGTH - 3] + "..." + + ret = json.dumps({"name": window_name, "class": window_class, "formatted_name": formatted_name}) + print(ret) + sys.stdout.flush() + + +if __name__ == "__main__": + main() diff --git a/home/.config/eww/scripts/workspaces b/home/.config/eww/scripts/workspaces new file mode 100755 index 0000000..0562b10 --- /dev/null +++ b/home/.config/eww/scripts/workspaces @@ -0,0 +1,12 @@ +#!/bin/bash + +# shellcheck source=include +source "./scripts/include" + +if [ "$1" = "--switch" ]; then + hyprctl dispatch workspace "$2" >/dev/null +elif [ "$1" = "--loop" ]; then + hyprland_ipc "workspace|createworkspace|destroyworkspace" | ./scripts/workspaces.py "$@" +else + ./scripts/workspaces.py "$@" +fi diff --git a/home/.config/eww/scripts/workspaces.py b/home/.config/eww/scripts/workspaces.py new file mode 100755 index 0000000..6f3fb58 --- /dev/null +++ b/home/.config/eww/scripts/workspaces.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +import argparse +import json +import subprocess +import sys +from typing import TypedDict, TYPE_CHECKING + +if TYPE_CHECKING: + from _typeshed import SupportsRichComparison + + +class WorkspaceInfo(TypedDict): + id: int + name: str + monitor: str + windows: int + hasfullscreen: bool + lastwindow: str + lastwindowtitle: str + + +class ActiveWorkspaceInfo(TypedDict): + id: int + name: str + + +class MonitorInfo(TypedDict): + id: int + name: str + description: str + width: int + height: int + refreshRate: float + x: int + y: int + activeWorkspace: ActiveWorkspaceInfo + reserved: list[int] + scale: float + transform: int + focused: bool + dpmsStatus: bool + + +class OutputWorkspaceInfo(WorkspaceInfo): + format_name: str + active: bool + + +# workspace id -> remapped name +REMAPS = { + 1: "", + 2: "", + 3: "", + 4: "", + 5: "", + 6: "", + 7: "7", + 8: "8", + 9: "9", +} + +# Skip the special (scratchpad) workspace +SKIP = {-99} + + +def workspace_sort(obj: OutputWorkspaceInfo) -> "SupportsRichComparison": + """Returns a key to sort by, given the current element.""" + return obj["id"] + + +def fill_blank_workspaces(open: list[OutputWorkspaceInfo]) -> list[OutputWorkspaceInfo]: + """Add in the rest of the workspaces which don't have any open windows on them. + + This is needed because hyprland deletes workspaces with nothing in them. + Note that this assumes all available workspaces were listed in REMAPS, and will + only fill those. These blank workspaces will have most string values set to "N/A", + and most int values set to 0. + """ + # Work on a copy, we don't want to alter the original list + lst = open.copy() + + for remap_id, format_name in REMAPS.items(): + # Skip for already present workspaces + if any(ws_info["id"] == remap_id for ws_info in lst): + continue + + blank_ws: OutputWorkspaceInfo = { + "id": remap_id, + "name": str(remap_id), + "monitor": "N/A", + "windows": 0, + "hasfullscreen": False, + "lastwindow": "N/A", + "lastwindowtitle": "N/A", + "active": False, + "format_name": format_name, + } + lst.append(blank_ws) + + return lst + + +def get_workspaces() -> list[OutputWorkspaceInfo]: + """Obtain workspaces from hyprctl, sort them and add format_name arg.""" + proc = subprocess.run(["hyprctl", "workspaces", "-j"], stdout=subprocess.PIPE) + proc.check_returncode() + workspaces: list[WorkspaceInfo] = json.loads(proc.stdout) + + proc = subprocess.run(["hyprctl", "monitors", "-j"], stdout=subprocess.PIPE) + proc.check_returncode() + monitors: list[MonitorInfo] = json.loads(proc.stdout) + + active_workspaces = {monitor["activeWorkspace"]["id"] for monitor in monitors} + + out: list[OutputWorkspaceInfo] = [] + for workspace in workspaces: + if workspace["id"] in SKIP: + continue + format_name = REMAPS.get(workspace["id"], workspace["name"]) + active = workspace["id"] in active_workspaces + out.append({**workspace, "format_name": format_name, "active": active}) + + out = fill_blank_workspaces(out) + out.sort(key=workspace_sort) + return out + + +def print_workspaces() -> None: + wks = get_workspaces() + ret = json.dumps(wks) + print(ret) + sys.stdout.flush() + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument( + "--oneshot", + action="store_true", + help="Don't listen to stdout for updates, only run once and quit", + ) + parser.add_argument( + "--loop", + action="store_true", + help="Listen to stdout input, once something is received, re-print workspaces" + ) + args = parser.parse_args() + + if args.loop and args.oneshot: + print("Can't use both --oneshot and --loop", file=sys.stdout) + sys.exit(1) + + if args.loop is None and args.oneshot is None: + print("No option specified!", file=sys.stdout) + sys.exit(1) + + # Print workspaces here immediately, we don't want to have to wait for the first + # update from stdin as we only receive those on actual workspace change. + print_workspaces() + + if args.oneshot: + # We've already printed the workspaces once, we can exit now + return + + # Reprint workspaces on each stdin update (flush) + for _ in sys.stdin: + print_workspaces() + + +if __name__ == "__main__": + main() diff --git a/home/.config/eww/windows/calendar.yuck b/home/.config/eww/windows/calendar.yuck new file mode 100644 index 0000000..610f00a --- /dev/null +++ b/home/.config/eww/windows/calendar.yuck @@ -0,0 +1,14 @@ +(defwidget calendar-win [] + (box + :class "calendar-win" + (calendar))) + +(defwindow calendar + :monitor 0 + :geometry (geometry + :x "0%" + :y "0%" + :anchor "top right" + :width "0px" + :height "0px") + (calendar-win)) diff --git a/home/.config/git/config b/home/.config/git/config new file mode 100644 index 0000000..d3421e3 --- /dev/null +++ b/home/.config/git/config @@ -0,0 +1,87 @@ +[user] + name = ItsDrike + email = itsdrike@protonmail.com + signingkey = B014E761034AF742 +[alias] + quickclone = "clone --single-branch --depth=1" + bareclone = "!sh -c 'git clone --bare \"$0\" \"$1\"/.bare; echo \"gitdir: ./.bare\" > \"$1/.git\"'" + bareinit = "!sh -c 'git init --bare \"$0\"/.bare; echo \"gitdir: ./.bare\" > \"$0/.git\"'" + cleanup = "!default_branch=$(git remote show origin | awk '/HEAD branch/ {print $NF}'); git remote prune origin && git checkout -q $default_branch && git for-each-ref refs/heads/ '--format=%(refname:short)' | while read branch; do mergeBase=$(git merge-base $default_branch $branch) && [[ $(git cherry $default_branch $(git commit-tree $(git rev-parse $branch^{tree}) -p $mergeBase -m _)) == '-'* ]] && git branch -D $branch; done" + + m = "merge" + p = "push" + pl = "pull" + f = "fetch" + + s = "status --short --branch" + ss = "status" + + ch = "checkout" + chb = "checkout -b" + + undo = "reset --soft HEAD~" + redo = "reset HEAD@{1}" + unstage = "restore --staged" + + c = "commit" + ca = "commit --ammend" + ci = "commit --interactive" + cm = "commit --message" + cv = "commit --verbose" + + a = "add" + aa = "add --all" + ap = "add --patch" + au = "add --update" + + d = "diff" + dc = "diff --cached" + ds = "diff --staged" + dw = "diff --word-diff" + dcm = "!sh -c 'git diff $0~ $0'" + + b = "branch" + ba = "branch --all" + bd = "branch --delete" + bD = "branch --delete --force" + bm = "branch --move" + bM = "branch --move --force" + + r = "rebase" + ri = "rebase -i" + rc = "rebase --continue" + + l = "log --oneline --decorate --all --graph" + lp = "log --patch" + lo = "log --pretty=oneline --abbrev-commit --graph" + lg = "log --all --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --" + + set-upstream = "!git branch --set-upstream-to=origin/`git symbolic-ref --short HEAD`" + + stash-staged = "!sh -c 'git stash --keep-index; git stash push -m \"staged\" --keep-index; git stash pop stash@{1}'" + + find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'" + show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'" + + comitter-lines = "!git log --author=\"$1\" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf \"added lines: %s, removed lines: %s, total lines: %s\\n\", add, subs, loc }' #" + total-lines = "!git ls-files | xargs cat | wc -l" +[credential] + helper = store --file ~/.config/git/git-credentials +[core] + excludefile = ~/.config/git/global_gitignore + editor = lvim + pager = delta +[interactive] + diffFilter = delta --color-only +[delta] + line-numbers = true +[merge] + conflictstyle = diff3 +[diff] + tool = vimdiff +[fetch] + prune = true +[commit] + gpgsign = true +[init] + defaultBranch = main diff --git a/home/.config/git/global_gitignore b/home/.config/git/global_gitignore new file mode 100644 index 0000000..366035c --- /dev/null +++ b/home/.config/git/global_gitignore @@ -0,0 +1,25 @@ +# vim: filetype=conf +# Byte-compiled / optimized / DLL Files +__pycache__/ +*.py[cod] +*$py.class + +# Virtual Environments +.venv/ + +# Editor project settings +## VSCode +.vscode/ +## PyCharm intellij +.idea/ +## repl.it +.replit +## spyder +.spyproject/ +.spyderproject/ + +# Custom attributes for folders on Mac OS +.DS_Store + +# Personal TODO files +TODO diff --git a/home/.config/gtk-2.0/gtkfilechooser.ini b/home/.config/gtk-2.0/gtkfilechooser.ini new file mode 100644 index 0000000..6171c6a --- /dev/null +++ b/home/.config/gtk-2.0/gtkfilechooser.ini @@ -0,0 +1,11 @@ +[Filechooser Settings] +LocationMode=path-bar +ShowHidden=false +ShowSizeColumn=true +GeometryX=510 +GeometryY=260 +GeometryWidth=900 +GeometryHeight=584 +SortColumn=name +SortOrder=ascending +StartupMode=recent diff --git a/home/.config/gtk-2.0/gtkrc b/home/.config/gtk-2.0/gtkrc new file mode 100644 index 0000000..7348f1a --- /dev/null +++ b/home/.config/gtk-2.0/gtkrc @@ -0,0 +1,19 @@ +# DO NOT EDIT! This file will be overwritten by LXAppearance. +# Any customization should be done in ~/.gtkrc-2.0.mine instead. + +include "/home/itsdrike/.gtkrc-2.0.mine" +gtk-theme-name="Adwaita-dark" +gtk-icon-theme-name="Papirus-Dark" +gtk-font-name="Noto Sans, 10" +gtk-cursor-theme-name="BreezeX-Light" +gtk-cursor-theme-size=24 +gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle="hintfull" +gtk-modules="colorreload-gtk-module:window-decorations-gtk-module:appmenu-gtk-module" diff --git a/home/.config/gtk-3.0/bookmarks b/home/.config/gtk-3.0/bookmarks new file mode 100644 index 0000000..4539c36 --- /dev/null +++ b/home/.config/gtk-3.0/bookmarks @@ -0,0 +1,3 @@ +file:///home/itsdrike/Pictures Pictures +file:///home/itsdrike/Downloads Downloads +file:///home/itsdrike/Personal Personal diff --git a/home/.config/gtk-3.0/settings.ini b/home/.config/gtk-3.0/settings.ini new file mode 100644 index 0000000..629ebe3 --- /dev/null +++ b/home/.config/gtk-3.0/settings.ini @@ -0,0 +1,21 @@ +[Settings] +gtk-application-prefer-dark-theme=true +gtk-button-images=1 +gtk-cursor-theme-name=BreezeX-Light +gtk-cursor-theme-size=24 +gtk-decoration-layout=icon:minimize,maximize,close +gtk-enable-animations=true +gtk-font-name=Noto Sans, 10 +gtk-icon-theme-name=Papirus-Dark +gtk-menu-images=1 +gtk-modules=colorreload-gtk-module:window-decorations-gtk-module:appmenu-gtk-module +gtk-primary-button-warps-slider=false +gtk-shell-shows-menubar=1 +gtk-theme-name=Adwaita-dark +gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ +gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle=hintfull diff --git a/home/.config/hypr/hyprland.conf b/home/.config/hypr/hyprland.conf new file mode 100644 index 0000000..937272a --- /dev/null +++ b/home/.config/hypr/hyprland.conf @@ -0,0 +1,204 @@ +# Should be configured per-profile +monitor = eDP-1, preferred, auto, 1 +workspace = eDP-1, 1 + +# Autostart +exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP +exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP +exec-once = hypr-restart-portals + +exec-once = setbg +# exec-once = waybar --config ~/.config/waybar/config-hypr >~/.waybar.txt 2>&1 +exec-once = dunst> +exec-once = swayidle + +exec-once = nm-applet +exec-once = aa-notify -p +exec-once = udiskie -A -T + +exec-once = webcord --start-minimized + + +input { + kb_layout = us, sk + kb_variant = ,qwerty + kb_options = grp:alt_shift_toggle + numlock_by_default=true + + follow_mouse = 1 + + touchpad { + natural_scroll = no + } +} + +general { + gaps_in = 5 + gaps_out = 8 + border_size = 2 + #col.active_border = 0xFF327BD1 # blue + col.active_border = 0xFFFFA500 # orange + col.inactive_border = 0xFF000000 # black + layout = dwindle +} + +decoration { + rounding = 8 + blur = 1 + blur_size = 3 + blur_passes = 2 + blur_new_optimizations = 1 + + drop_shadow = 1 + shadow_ignore_window = 1 + shadow_offset = 2 2 + shadow_range = 4 + shadow_render_power = 1 + col.shadow = 0x55000000 +} + +animations { + enabled = 1 + animation = windows, 1, 3, default, popin 50% + animation = border, 1, 4, default + animation = fade, 1, 4, default + animation = workspaces, 1, 3, default +} + +dwindle { + pseudotile = 1 + preserve_split = 1 + no_gaps_when_only = 0 +} + +# Automatically move windows to their workspace +windowrulev2 = workspace 2, class:^(firefox)$ +windowrulev2 = workspace 4, class:^(discord)$ +windowrulev2 = workspace 4, class:^(WebCord)$ +windowrulev2 = workspace 6, class:^(Stremio)$ + +# Give apps proper size +windowrulev2 = float, class:^(qalculate-gtk)$ +windowrulev2 = size 800 550, class:^(qalculate-gtk)$ + + +# Mouse window resizing +bindm = SUPER, mouse:272, movewindow +bindm = SUPER, mouse:273, resizewindow + +# Compositor commands +bind = SUPER, Space, fullscreen, +bind = SUPER, W, killactive, +bind = SUPER, F, togglefloating, +bind = SUPER, S, togglesplit, +bind = SUPER, G, togglegroup, +bind = SUPER_SHIFT, N, changegroupactive, f +bind = SUPER_SHIFT, P, changegroupactive, b +bind = SUPER, P, pseudo, +bind = SUPER_SHIFT, Q, exit, # TODO: Use pkill and prompt for confirm + +# Utilities +bind = SUPER_CTRL, L, exec, swaylock -fF +bind = SUPER_SHIFT, L, exec, wlogout -p layer-shell + +# Programs +bind = SUPER, Return, exec, alacritty +bind = SUPER, X, exec, pcmanfm +bind = SUPER, B, exec, firefox +bind = SUPER, R, exec, wofi --show drun +bind = SUPER_SHIFT, Return, exec, wofi --show run + +# Notifications +bind = CTRL, grave, exec, dunstctl close +bind = CTRL_SHIFT, grave, exec, dunstctl close-all +bind = CTRL, period, exec, dunstctl history-pop +bind = CTRL_SHIFT, period, exec, dunstctl context + +# Volume comtrol +binde = SUPER, Down, exec, pulsemixer --change-volume -5 +binde = SUPER, Up, exec,pulsemixer --change-volume +5 +binde = , XF86AudioLowerVolume, exec, pulsemixer --change-volume -5 +binde = , XF86AudioRaiseVolume, exec, pulsemixer --change-volume +5 +bind = , XF86AudioMute, exec, pulsemixer --toggle-mute + +# Brightness control +binde = SUPER, Right, exec, brightness -i 5% -n +binde = SUPER, Left, exec, brightness -d 5% -n +binde = , XF86MonBrightnessUp, exec, brightness -i 5% -n +binde = , XF86MonBrightnessDown, exec, brightness -d 5% -n + +# Screenshots +bind = ,Print, exec, grim -g "$(slurp)" - | wl-copy && notify-send "Screenshot" "Screenshot saved to clipboard" +bind = SUPER, Print, exec, grim -g "$(slurp)" - | swappy -f - -o - | wl-copy +bind = CTRL, Print, exec, echo "" | wofi --prompt "Set delay (ms)" --show dmenu | xargs -I _ sleep _e-3 && grim -g "$(slurp)" - | wl-copy +bind = SUPER_CTRL, Print, exec, echo "" | wofi --prompt "Set delay (ms)" --show dmenu | xargs -I _ sleep _e-3 && grim -g "$(slurp)" - | swappy -f - -o - | wl-copy +bind = SHIFT, Print, exec, wl-copy "$(hyprpicker)" && notify-send 'Picked color' "$(wl-paste) (saved to clipboard)" + +# Move between windows +bind = SUPER, h, movefocus, l +bind = SUPER, l, movefocus, r +bind = SUPER, k, movefocus, u +bind = SUPER, j, movefocus, d + +# Window resizing +bind = SUPER, Q, submap, resize +submap = resize +binde = , right, resizeactive, 10 0 +binde = , left, resizeactive, -10 0 +binde = , up, resizeactive, 0 -10 +binde = , down, resizeactive, 0 10 +binde = , L, resizeactive, 10 0 +binde = , H, resizeactive, -10 0 +binde = , K, resizeactive, 0 -10 +binde = , J, resizeactive, 0 10 +bind = , escape, submap, reset +bind = SUPER, Q, submap, reset +submap = reset + +# Move between workspaces +bind = SUPER, 1, workspace, 1 +bind = SUPER, 2, workspace, 2 +bind = SUPER, 3, workspace, 3 +bind = SUPER, 4, workspace, 4 +bind = SUPER, 5, workspace, 5 +bind = SUPER, 6, workspace, 6 +bind = SUPER, 7, workspace, 7 +bind = SUPER, 8, workspace, 8 +bind = SUPER, 9, workspace, 9 + +# Move windows to workspaces +bind = SUPER_SHIFT, 1, movetoworkspacesilent, 1 +bind = SUPER_SHIFT, 2, movetoworkspacesilent, 2 +bind = SUPER_SHIFT, 3, movetoworkspacesilent, 3 +bind = SUPER_SHIFT, 4, movetoworkspacesilent, 4 +bind = SUPER_SHIFT, 5, movetoworkspacesilent, 5 +bind = SUPER_SHIFT, 6, movetoworkspacesilent, 6 +bind = SUPER_SHIFT, 7, movetoworkspacesilent, 7 +bind = SUPER_SHIFT, 8, movetoworkspacesilent, 8 +bind = SUPER_SHIFT, 9, movetoworkspacesilent, 9 + + +# Move windows to workspaces and focus it there +bind = ALT, 1, movetoworkspace, 1 +bind = ALT, 2, movetoworkspace, 2 +bind = ALT, 3, movetoworkspace, 3 +bind = ALT, 4, movetoworkspace, 4 +bind = ALT, 5, movetoworkspace, 5 +bind = ALT, 6, movetoworkspace, 6 +bind = ALT, 7, movetoworkspace, 7 +bind = ALT, 8, movetoworkspace, 8 +bind = ALT, 9, movetoworkspace, 9 + +# Cycle workspaces +bind = SUPER, mouse_down, workspace, m+1 +bind = SUPER, mouse_up, workspace, m-1 +bind = SUPER, bracketleft, workspace, m-1 +bind = SUPER, bracketright, workspace, m+1 + +# Cycle monitors +bind = SUPER_SHIFT, braceleft, focusmonitor, l +bind = SUPER_SHIFT, braceright, focusmonitor, r + +# Special workspace +bind = ALT, grave, movetoworkspace, special +bind = SUPER, grave, togglespecialworkspace, diff --git a/home/.config/java/.keep b/home/.config/java/.keep new file mode 100644 index 0000000..e69de29 diff --git a/home/.config/lf/clear_img.sh b/home/.config/lf/clear_img.sh new file mode 100755 index 0000000..dbc35d7 --- /dev/null +++ b/home/.config/lf/clear_img.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +readonly PREVIEW_ID="preview" + +printf '{"action": "remove", "identifier": "%s"}\n' "$PREVIEW_ID" > "$FIFO_UEBERZUG" + diff --git a/home/.config/lf/draw_img.sh b/home/.config/lf/draw_img.sh new file mode 100755 index 0000000..1547ca0 --- /dev/null +++ b/home/.config/lf/draw_img.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +path="$1" +x="$2" +y="$3" +width="$4" +height="$5" +PREVIEW_ID="preview" + +if [ -n "$FIFO_UEBERZUG" ]; then + printf '{"action": "add", "identifier": "%s", "x": %d, "y": %d, "width": %d, "height": %d, "scaler": "contain", "scaling_position_x": 0.5, "scaling_position_y": 0.5, "path": "%s"}\n' \ + "$PREVIEW_ID" "$x" "$y" "$width" "$height" "$path" > "$FIFO_UEBERZUG" +else + # Ueberzug isn't avialable, try to use pixterm + if command -v pixterm > /dev/null; then + pixterm -s 2 -tr "$x" -tc "$width" "$path" + else + >&2 echo "ueberzug not running, pixterm fallback not found!" + exit 1 + fi +fi diff --git a/home/.config/lf/lfrc b/home/.config/lf/lfrc new file mode 100644 index 0000000..8857c5e --- /dev/null +++ b/home/.config/lf/lfrc @@ -0,0 +1,144 @@ +# Basic settings +set previewer ~/.config/lf/previewer.sh +set cleaner ~/.config/lf/clear_img.sh +set preview true +set hidden true +set drawbox true +set icons true +set ignorecase true +set scrolloff 5 + +# Use $EDITOR for text +cmd open ${{ + case $(file --mime-type "$f" -bL) in + text/*|application/json) $EDITOR "$f";; + *) devour xdg-open "$f" ;; + esac +}} + +# File/Directory control functions +cmd mkdir %{{ + printf "Directory Name: " + read ans + mkdir $ans +}} + +cmd mkfile %{{ + printf "File Name: " + read ans + touch $ans +}} + +cmd chmod %{{ + printf "Mode Bits: " + read ans + + for file in "$fx"; do + chmod $ans $file + done + + lf -remote 'send reload' +}} + +# Add z.lua functionality for easy autojumps +cmd zlua %{{ + printf "z.lua input: " + read ans + + /usr/local/src/z.lua/z.lua $ans +}} + + +# Archive bindings +cmd unarchive ${{ + case "$f" in + *.zip) unzip "$f" ;; + *.tar.gz) tar -xzvf "$f" ;; + *.tar.bz2) tar -xjvf "$f" ;; + *.tar) tar -xvf "$f" ;; + *) echo "Unsuported format" ;; + esac +}} + +cmd zip %zip -r "$f" "$f" +cmd tar %tar cvf "$f.tar" "$f" +cmd targz %tar cvzf "%f.tar.gz" "$f" +cmd tarbz2 %tar cjvf "$f.tar.bz2" "$f" + +# Trash-cli bindings +cmd trash ${{ + files=$(printf "$fx" | tr '\n' ':') + while [ "$files" ]; do + # extract the substring from start of string up to delimeter. + # this is the first "element" of the string + file=${files%%:*} + + trash-put "$(basename "$file")" + # if there's only one element left, set `files` to an empty string. + # this causes us to exit this `while` loop. + # else, we delete the first "element" of the string from files, and + # move onto the next. + if [ "$files" = "$file" ]; then + files='' + else + files="${files#*;}" + fi + done +}} + +cmd clear_trash %trash-empty + +cmd restore_trash ${{ + trash-restore +}} + +# Bindings +# Remove some defaults +map m +map n +map "'" +map '"' +map d +map c + +# Archive mappings +map az zip +map at tar +map ag targz +map au unarchive + +# Trash mappings +map dd trash +map tc clear_trash +map tr restore_trash + +# Basic functions +map . set hidden! +map DD delete +map p paste +map x cut +map y copy +map open +map md mkdir +map mf mkfile +map ch chmod +map r rename +map H top +map L bottom +map R reload +map C clear +map z zlua + +# Movement +map gh cd ~ +map gc cd ~/.config +map gl cd ~/.local +map gs cd ~/.local/bin/scripts +map gtr cd ~/.local/share/Trash/files +map gE. cd /etc +map gEp cd /etc/portage +map gU. cd /usr +map gUs cd /usr/share +map gUl cd /usr/local +map gM cd /mnt + diff --git a/home/.config/lf/previewer.sh b/home/.config/lf/previewer.sh new file mode 100755 index 0000000..73784f3 --- /dev/null +++ b/home/.config/lf/previewer.sh @@ -0,0 +1,162 @@ +#!/bin/sh +# This script handles showing file-previews within lf. + +# It can also show image previews using ueberzug, however +# that requires lf to be started with a script that also starts +# ueberzug alongside of it. +# (In my dotfiles, this script is in '~/.local/bin/scripts/lfu') +# Alternatively, we could also handle ANSI previews with pixterms +# this will be in a pretty low quiality, but it will work without +# ueberzug. To enable this, change PIXTERM_ENABLED to 1. +# if both ueberzug and pixterm are enabled, ueberzug takes precedence. +PIXTERM_ENABLED=1 + +run_cmd() { + # Try to run given command, if it is installed. + # If it isn't try to fallback to text_handle, + # otherwise fail completely. + cmd="$1" + shift + + if command -v "$cmd" > /dev/null; then + $cmd $@ + else + # If we didn't found the requested command, check if + # the file is text-like and try to use the text_handle + # to show the preview, this may not be ideal for given + # file-format, but at least we won't fail. + case $(file --mime-type "$1" -bL) in + # TODO: Consider checking for UTF-8 formatting instead, + # or show previews for any file-type + text/*|application/json) + echo "@@PREVIEW FALLBACK: Using text handle, $cmd command not found!" + text_handle "$1" + ;; + *) + echo "@@PREVIEW ERROR: Preview failed, $cmd command not found!" + ;; + esac + fi +} + +draw_image() { + # Draw passed image with use of given draw_script. + # If the image contains EXIF (metadata) orientation info, + # handle it and draw the rotated image. + draw_script="$1" + file="$2" + shift + shift + + # Calculate where the image should be placed on the screen. + num=$(printf "%0.f\n" "`echo "$(tput cols) / 2" | bc`") + numb=$(printf "%0.f\n" "`echo "$(tput cols) - $num - 1" | bc`") + numc=$(printf "%0.f\n" "`echo "$(tput lines) - 2" | bc`") + + # Handle EXIF (metadata) orientation. + exif_orientation="$(identify -format '%[EXIF:Orientation]\n' -- "$file")" + if [ -n "$exif_orientation" ] && [ "$exif_orientation" != 1 ]; then + # In case `convert` command isn't aviable, ignore EXIF rotation + if command -v convert > /dev/null; then + cache=$(mktemp /tmp/thumbcache.XXXXX) + convert -- "$file" -auto-orient "$cache" + $draw_script "$cache" $num 1 $numb $numc + else + $draw_script "$file" $num 1 $numb $numc + fi + else + $draw_script "$file" $num 1 $numb $numc + fi + + # Exit with status code 1 to signal lf that the function + # should be re-ran next time instead of caching the result. + exit 1 +} + +media_handle() { + # Handle media type files (videos, photos). These types of + # files are usually not stored in any form of textually readable + # format and they require a special way of displaying them. + # This mostly uses ueberzug (if available) for this. + + draw_script="${XDG_CONFIG_HOME:-$HOME/.config}/lf/draw_img.sh" + file="$1" + shift + + # Set ENABLED=1 if ueberzug or pixterm is enabled + command -v pixterm > /dev/null && [ "$PIXTERM_ENABLED" = 1 ] && ENABLED=1 + [ -n "$FIFO_UEBERZUG" ] && [ -f "$draw_script" ] && ENABLED=1 + + case "$file" in + *.bmp|*.jpg|*.jpeg|*.png|*.xpm) + if [ -n "$ENABLED" ]; then + draw_image $draw_script "$file" + else + echo "@@PREVIEW FALLBACK: Using mediainfo, ueberzug isn't available." + run_cmd mediainfo "$file" + fi + ;; + *.avi|*.mp4|*.wmv|*.dat|*.3gp|*.ogv|*.mkv|*.mpg|*.mpeg|*.vob|*.fl[icv]|*.m2v|\ + *.mov|*.webm|*.ts|*.mts|*.m4v|*.r[am]|*.qt|*.divx) + if [ -n "$ENABLED" ]; then + cache="$(mktemp /tmp/thumbcache.XXXXX)" + ffmpegthumbnailer -i "$file" -o "$cache" -s 0 + draw_image $draw_script "$cache" + else + echo "@@PREVIEW FALLBACK: Using exiftool, ueberzug isn't aviable." + run_cmd exiftool "$file" + fi + ;; + *.wav|*.mp3|*.flac|*.m4a|*.wma|*.ape|*.ac3|*.og[agx]|*.spx|*.opus|*.as[fx]|*.flac) + # These types can't make use of ueberzug easily, so simply use eixftool + run_cmd exiftool "$file" + ;; + *) + echo "@@PREVIEW FALLBACK: Unrecognized media file, falling back to text handle." + text_handle "$file" + ;; + esac +} + +text_handle() { + # Handle all other formats as text and cat them + # if highlighting tools are aviable, try to use them + if command -v bat > /dev/null; then + num=$(printf "%0.f\n" "`echo "$(tput cols) / 2" | bc`") + numb=$(printf "%d\n" "`echo "$(tput cols) - $num - 3" | bc`") + bat -pp --color=always --wrap=character --terminal-width="$numb" "$1" + elif command -v highlight > /dev/null; then + highlight "$1" --out-format ansi --force + else + cat "$1" + fi +} + +# Capture all directories at first, since they could +# potentionally match one of the file case statements +if [ -d "$1" ]; then + tree "$1" -La 1 +elif [ -f "$1" ]; then + case "$1" in + *.tgz|*.tar.gz) run_cmd tar tzf "$1";; + *.tar.bz2|*.tbz2) run_cmd tar tjf "$1";; + *.tar.txz|*.txz) run_cmd xz --list "$1";; + *.tar) run_cmd tar tf "$1";; + *.zip|*.jar|*.war|*.ear|*.oxt) run_cmd unzip -l "$1";; + *.rar) run_cmd unrar l "$1";; + *.7z) run_cmd 7z l "$1";; + *.iso) run_cmd iso-info --no-header -l "$1";; + *.o) run_cmd nm "$1" | less ;; + *.csv) cat "$1" | sed s/,/\\n/g ;; + *odt,*.ods,*.odp,*.sxw) run_cmd odt2txt "$1";; + *.doc) run_cmd catdoc "$1" ;; + *.docx) run_cmd docx2txt "$1" - ;; + *.torrent) run_cmd transmission-show "$1";; + *.pdf) run_cmd pdftotext "$1";; + *.wav|*.mp3|*.flac|*.m4a|*.wma|*.ape|*.ac3|*.og[agx]|*.spx|*.opus|*.as[fx]|*.flac|\ + *.avi|*.mp4|*.wmv|*.dat|*.3gp|*.ogv|*.mkv|*.mpg|*.mpeg|*.vob|*.fl[icv]|*.m2v|*.mov|\ + *.webm|*.ts|*.mts|*.m4v|*.r[am]|*.qt|*.divx|\ + *.bmp|*.jpg|*.jpeg|*.png|*.xpm) media_handle "$1" ;; + *) text_handle "$1" ;; + esac +fi diff --git a/home/.config/lvim/.luacheckrc b/home/.config/lvim/.luacheckrc new file mode 100644 index 0000000..089f44b --- /dev/null +++ b/home/.config/lvim/.luacheckrc @@ -0,0 +1,43 @@ +-- vim: ft=lua tw=80 + +stds.nvim = { + globals = { + "lvim", + vim = { fields = { "g" } }, + "TERMINAL", + "USER", + "C", + "Config", + "WORKSPACE_PATH", + "JAVA_LS_EXECUTABLE", + "MUtils", + "USER_CONFIG_PATH", + os = { fields = { "capture" } }, + }, + read_globals = { + "jit", + "os", + "vim", + "join_paths", + "get_runtime_dir", + "get_config_dir", + "get_cache_dir", + "get_lvim_base_dir", + "require_clean", + }, +} + +std = "lua51+nvim" + +files["tests/*_spec.lua"].std = "lua51+nvim+busted" + +-- Don't report unused self arguments of methods. +self = false + +-- Rerun tests only if their modification time changed. +cache = true + +ignore = { + "631", -- max_line_length + "212/_.*", -- unused argument, for vars with "_" prefix +} diff --git a/home/.config/lvim/.stylua.toml b/home/.config/lvim/.stylua.toml new file mode 100644 index 0000000..df96b7b --- /dev/null +++ b/home/.config/lvim/.stylua.toml @@ -0,0 +1,6 @@ +column_width = 120 +line_endings = "Unix" +indent_type = "Spaces" +indent_width = 2 +quote_style = "AutoPreferDouble" +no_call_parentheses = true diff --git a/home/.config/lvim/after/ftplugin/python.lua b/home/.config/lvim/after/ftplugin/python.lua new file mode 100644 index 0000000..8395fbb --- /dev/null +++ b/home/.config/lvim/after/ftplugin/python.lua @@ -0,0 +1,2 @@ +local dap_install = require "dap-install" +dap_install.config("python", {}) diff --git a/home/.config/lvim/config.lua b/home/.config/lvim/config.lua new file mode 100644 index 0000000..152a91a --- /dev/null +++ b/home/.config/lvim/config.lua @@ -0,0 +1,43 @@ +require "user.keys" +require "user.abbreviations" +require "user.lsp" +require "user.autocmds" +require "user.plugins" +require "user.options" +require "user.lualine" +require "user.treesitter" + +-- TEMPORARY; Learn vim, the hard way +-- vim.opt.mouse = {} +-- lvim.keys.normal_mode[""] = "" +-- lvim.keys.normal_mode[""] = "" +-- lvim.keys.normal_mode[""] = "" +-- lvim.keys.normal_mode[""] = "" +-- lvim.keys.visual_mode[""] = "" +-- lvim.keys.visual_mode[""] = "" +-- lvim.keys.visual_mode[""] = "" +-- lvim.keys.visual_mode[""] = "" +-- lvim.keys.insert_mode[""] = "" +-- lvim.keys.insert_mode[""] = "" +-- lvim.keys.insert_mode[""] = "" +-- lvim.keys.insert_mode[""] = "" + + +-- general +lvim.log.level = "warn" +lvim.format_on_save = false +lvim.colorscheme = "onedarker" +-- to disable icons and use a minimalist setup, uncomment the following +-- lvim.use_icons = false + +-- TODO: User Config for predefined plugins +-- After changing plugin config exit and reopen LunarVim, Run :PackerInstall :PackerCompile +lvim.builtin.dap.active = true +lvim.builtin.notify.active = true +lvim.builtin.terminal.active = true +lvim.builtin.alpha.active = true +lvim.builtin.alpha.mode = "dashboard" +lvim.builtin.nvimtree.setup.view.side = "left" +lvim.builtin.project.patterns = { ".git", ".svn" } +lvim.builtin.bufferline.options.always_show_bufferline = true +-- lvim.builtin.nvimtree.setup.renderer.icons.show.git = false diff --git a/home/.config/lvim/ftdetect/apparmor.lua b/home/.config/lvim/ftdetect/apparmor.lua new file mode 100644 index 0000000..c27f5b7 --- /dev/null +++ b/home/.config/lvim/ftdetect/apparmor.lua @@ -0,0 +1,11 @@ +local autocmd = vim.api.nvim_create_autocmd + +autocmd({ "BufNewFile", "BufRead" }, { + pattern = { "/etc/apparmor.d/*" }, + command = "setfiletype apparmor" +}) + +autocmd({ "BufNewFile", "BufRead" }, { + pattern = { "/usr/share/apparmor/extra-profiles/*" }, + command = "setfiletype apparmor" +}) diff --git a/home/.config/lvim/ftdetect/axaml.lua b/home/.config/lvim/ftdetect/axaml.lua new file mode 100644 index 0000000..1204c37 --- /dev/null +++ b/home/.config/lvim/ftdetect/axaml.lua @@ -0,0 +1,6 @@ +local autocmd = vim.api.nvim_create_autocmd + +autocmd({ "BufNewFile", "BufRead" }, { + pattern = { "*.axaml" }, + command = "setfiletype xml" +}) diff --git a/home/.config/lvim/lua/user/abbreviations.lua b/home/.config/lvim/lua/user/abbreviations.lua new file mode 100644 index 0000000..658a51b --- /dev/null +++ b/home/.config/lvim/lua/user/abbreviations.lua @@ -0,0 +1,30 @@ +-- Define an abbreviation +local function abbrev(mode, input, result, reabbrev) + reabbrev = reabbrev or false + local command + if reabbrev then + command = mode .. "abbrev" + else + command = mode .. "noreabbrev" + end + vim.cmd(command .. " " .. input .. " " .. result) +end + +-- In case I have caps on (don't judge me for using caps) +abbrev("c", "Wq", "wq") +abbrev("c", "wQ", "wq") +abbrev("c", "WQ", "wq") +abbrev("c", "WQ!", "wq") +abbrev("c", "wQ!", "wq") +abbrev("c", "Wq!", "wq") +abbrev("c", "W", "w") +abbrev("c", "W!", "w!") +abbrev("c", "Q", "q!") +abbrev("c", "Q!", "q!") +abbrev("c", "Qall", "qall") +abbrev("c", "Qall!", "qall") +abbrev("c", "QALL", "qall") +abbrev("c", "QALL!", "qall") + +-- Save file with sudo +abbrev("c", "w!!", "w !sudo tee > /dev/null %") diff --git a/home/.config/lvim/lua/user/autocmds.lua b/home/.config/lvim/lua/user/autocmds.lua new file mode 100644 index 0000000..2c873a3 --- /dev/null +++ b/home/.config/lvim/lua/user/autocmds.lua @@ -0,0 +1,19 @@ +-- Autocommands (https://neovim.io/doc/user/autocmd.html) + +-- Delete all trailing whitespace on saving +vim.api.nvim_create_autocmd("BufWritePre", { pattern = "*.py", command = [[%s/\s\+$//e]] }) +-- Set text wrap to 119 characters +vim.api.nvim_create_autocmd("BufWinEnter", { pattern = "*.md", command = "setlocal tw=119" }) +-- Jump to last position when opening a file +vim.api.nvim_create_autocmd("BufReadPost", { + pattern = "*", + command = [[if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif]], +}) +-- Highlight current line number +vim.api.nvim_create_autocmd("ColorScheme", { pattern = "*", command = "highlight CursorLine guibg=#2b2b2b" }) +vim.api.nvim_create_autocmd("ColorScheme", { + pattern = "*", + command = "highlight CursorLineNr guifg=#1f85de ctermfg=LightBlue", +}) +-- Custom syntax definitions based on file extensions +vim.api.nvim_create_autocmd("BufRead", { pattern = "*.axml", command = "set ft=xml" }) diff --git a/home/.config/lvim/lua/user/keys.lua b/home/.config/lvim/lua/user/keys.lua new file mode 100644 index 0000000..d0b657e --- /dev/null +++ b/home/.config/lvim/lua/user/keys.lua @@ -0,0 +1,118 @@ +-- keymappings [view all the defaults by pressing Lk] +lvim.leader = "space" + +-- Common shortcuts +lvim.keys.normal_mode[""] = ":w" +lvim.keys.insert_mode[""] = ":wi" +lvim.keys.normal_mode[""] = ":undo" +lvim.keys.normal_mode[""] = ":redo" + +-- Moevements +lvim.keys.normal_mode["H"] = "^" +lvim.keys.normal_mode["L"] = "$" + +-- Moving through buffers +lvim.keys.normal_mode[""] = ":BufferLineCycleNext" +lvim.keys.normal_mode[""] = ":BufferLineCyclePrev" +lvim.keys.normal_mode[""] = ":BufferLineMoveNext" +lvim.keys.normal_mode[""] = ":BufferLineMovePrev" + +-- Opening various menus +lvim.keys.normal_mode[""] = ":NvimTreeFindFileToggle" +lvim.keys.normal_mode[""] = ":Lf" +lvim.keys.normal_mode[""] = ":MinimapToggle" +lvim.keys.normal_mode[""] = ":SymbolsOutline" + +-- Delete to void register +lvim.keys.visual_mode[""] = '"_d' +lvim.keys.normal_mode[""] = '"_d' +lvim.keys.visual_mode[""] = '"_dP' +lvim.keys.visual_mode["p"] = '"_dP' + +-- Remove highlight +lvim.keys.normal_mode[""] = ":nohlsearch" + +-- Debugger +lvim.keys.normal_mode[""] = ":DapToggleBreakpoint" +lvim.keys.normal_mode[""] = ":DapContinue" +lvim.keys.normal_mode[""] = ":DapToggleRepl" +lvim.keys.normal_mode[""] = ":DapTerminate" +lvim.keys.normal_mode[""] = ":DapStepOver" +lvim.keys.normal_mode[""] = ":DapStepInto" +lvim.keys.normal_mode[""] = ":DapStepOut" + +lvim.builtin.which_key.mappings["h"] = { + name = "+Hop", + w = { "HopWord", "Word" }, + p = { "HopPattern", "Pattern" }, + a = { "HopAnywhere", "Anywhere" }, + v = { "HopVertical", "Vertical" }, +} + +-- Quick word replacing (use . for next word) +lvim.keys.normal_mode["cn"] = "*``cgn" +lvim.keys.normal_mode["cN"] = "*``cgN" + +-- Quick replace all +vim.api.nvim_set_keymap("n", "", "", { + noremap = true, + callback = function() + vim.fn.inputsave() + local query = vim.fn.input "To replace: " + + vim.fn.inputsave() + local answer = vim.fn.input("Replace text: ", query) + vim.api.nvim_command("%s/\\V" .. query:gsub("/", "\\/") .. "/" .. answer:gsub("/", "\\/") .. "/") + vim.fn.inputrestore() + vim.api.nvim_feedkeys("v", "n", false) + end, +}) +vim.api.nvim_set_keymap("v", "", "", { + noremap = true, + callback = function() + local getselection = function() + return vim.fn.strcharpart(vim.fn.getline(vim.fn.line "."), vim.fn.min { + vim.fn.charcol ".", + vim.fn.charcol "v", + } - 1, vim.fn.abs(vim.fn.charcol "." - vim.fn.charcol "v") + 1) + end + + local query = getselection() + + vim.fn.inputsave() + local answer = vim.fn.input("Replace text: ", query) + vim.api.nvim_command("%s/\\V" .. query:gsub("/", "\\/") .. "/" .. answer:gsub("/", "\\/") .. "/") + vim.fn.inputrestore() + vim.api.nvim_feedkeys("v", "n", false) + end, +}) + +-- Change Telescope navigation to use j and k for navigation and n and p for history in both input and normal mode. +-- we use protected-mode (pcall) just in case the plugin wasn't loaded yet. +-- local _, actions = pcall(require, "telescope.actions") +-- lvim.builtin.telescope.defaults.mappings = { +-- -- for input mode +-- i = { +-- [""] = actions.move_selection_next, +-- [""] = actions.move_selection_previous, +-- [""] = actions.cycle_history_next, +-- [""] = actions.cycle_history_prev, +-- }, +-- -- for normal mode +-- n = { +-- [""] = actions.move_selection_next, +-- [""] = actions.move_selection_previous, +-- }, +-- } + +-- Use which-key to add extra bindings with the leader-key prefix +-- lvim.builtin.which_key.mappings["P"] = { "Telescope projects", "Projects" } +-- lvim.builtin.which_key.mappings["t"] = { +-- name = "+Trouble", +-- r = { "Trouble lsp_references", "References" }, +-- f = { "Trouble lsp_definitions", "Definitions" }, +-- d = { "Trouble document_diagnostics", "Diagnostics" }, +-- q = { "Trouble quickfix", "QuickFix" }, +-- l = { "Trouble loclist", "LocationList" }, +-- w = { "Trouble workspace_diagnostics", "Workspace Diagnostics" }, +-- } diff --git a/home/.config/lvim/lua/user/lsp.lua b/home/.config/lvim/lua/user/lsp.lua new file mode 100644 index 0000000..35eb228 --- /dev/null +++ b/home/.config/lvim/lua/user/lsp.lua @@ -0,0 +1,68 @@ +-- generic LSP settings + +-- -- make sure server will always be installed even if the server is in skipped_servers list +-- lvim.lsp.installer.setup.ensure_installed = { +-- "sumeko_lua", +-- "jsonls", +-- } +-- -- change UI setting of `LspInstallInfo` +-- -- see +-- lvim.lsp.installer.setup.ui.check_outdated_servers_on_open = false +-- lvim.lsp.installer.setup.ui.border = "rounded" +-- lvim.lsp.installer.setup.ui.keymaps = { +-- uninstall_server = "d", +-- toggle_server_expand = "o", +-- } + +-- ---@usage disable automatic installation of servers +lvim.lsp.installer.setup.automatic_installation = false + +-- ---configure a server manually. !!Requires `:LvimCacheReset` to take effect!! +-- ---see the full default list `:lua print(vim.inspect(lvim.lsp.automatic_configuration.skipped_servers))` +-- vim.list_extend(lvim.lsp.automatic_configuration.skipped_servers, { "pyright" }) +-- local opts = {} -- check the lspconfig documentation for a list of all possible options +-- require("lvim.lsp.manager").setup("pyright", opts) + +-- ---remove a server from the skipped list, e.g. eslint, or emmet_ls. !!Requires `:LvimCacheReset` to take effect!! +-- ---`:LvimInfo` lists which server(s) are skipped for the current filetype +-- lvim.lsp.automatic_configuration.skipped_servers = vim.tbl_filter(function(server) +-- return server ~= "emmet_ls" +-- end, lvim.lsp.automatic_configuration.skipped_servers) + +-- -- you can set a custom on_attach function that will be used for all the language servers +-- -- See +-- lvim.lsp.on_attach_callback = function(client, bufnr) +-- local function buf_set_option(...) +-- vim.api.nvim_buf_set_option(bufnr, ...) +-- end +-- --Enable completion triggered by +-- buf_set_option("omnifunc", "v:lua.vim.lsp.omnifunc") +-- end + +-- set a formatter, this will override the language server formatting capabilities (if it exists) +lvim.format_on_save = false +local formatters = require "lvim.lsp.null-ls.formatters" +formatters.setup { + -- each formatter accepts a list of options identical to + -- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md#Configuration + { command = "black", filetypes = { "python" } }, + { command = "isort", filetypes = { "python" } }, + { + command = "prettier", + extra_args = { "--print-width", "100" }, + filetypes = { "typescript", "typescriptreact" }, + }, + { command = "stylua", filetypes = { "lua" } }, + -- { command = "rustfmt", filetypes = { "rust" } }, +} + +-- set additional linters +local linters = require "lvim.lsp.null-ls.linters" +linters.setup { + -- Each linter accepts a list of options identical to + -- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md#Configuration + { command = "flake8", filetypes = { "python" } }, + { command = "shellcheck", extra_args = { "--severity", "warning" } }, + { command = "codespell", filetypes = { "javascript", "python" } }, + { command = "luacheck", filetypes = { "lua" } }, +} diff --git a/home/.config/lvim/lua/user/lualine.lua b/home/.config/lvim/lua/user/lualine.lua new file mode 100644 index 0000000..d3635c6 --- /dev/null +++ b/home/.config/lvim/lua/user/lualine.lua @@ -0,0 +1,3 @@ +-- Add location (row:col) to lualine +local components = require "lvim.core.lualine.components" +lvim.builtin.lualine.sections.lualine_z = { components.location } diff --git a/home/.config/lvim/lua/user/options.lua b/home/.config/lvim/lua/user/options.lua new file mode 100644 index 0000000..87c4cf2 --- /dev/null +++ b/home/.config/lvim/lua/user/options.lua @@ -0,0 +1,24 @@ +-- Show whitespaces +vim.opt.list = true -- Enable showing characters like , +vim.opt.listchars = { tab = " ", trail = "·" } -- Specify which characters to show + +-- Theme options +vim.opt.cursorline = true -- Highlight cursor line +vim.opt.laststatus = 2 -- Always show status line +vim.opt.relativenumber = true -- Use relative line numbers +vim.opt.wrap = true -- Allow line wrapping + +-- Tab/Indent settings +-- vim.opt.autoindent = true -- Enable automatic indenting +-- vim.opt.expandtab = true -- Expand tabs into spaces +-- vim.opt.tabstop = 2 -- Number of spaces a tab in file accounts for +-- vim.opt.shiftwidth = 4 -- Indentation size for Tab +-- vim.opt.softtabstop = 4 -- Tabs/Spaces interlop +-- vim.opt.tabpagemax = 50 -- More tabs +-- vim.opt.shiftround = true -- Always round indent to multiple of shiftwidth + +-- Enable syntax highlighting in fenced markdown code-blocks +vim.g.markdown_fenced_languages = {"html", "javascript", "typescript", "css", "scss", "lua", "vim", "python"} + +-- Other +vim.opt.shell = "/bin/sh" diff --git a/home/.config/lvim/lua/user/plugins.lua b/home/.config/lvim/lua/user/plugins.lua new file mode 100644 index 0000000..ef432f3 --- /dev/null +++ b/home/.config/lvim/lua/user/plugins.lua @@ -0,0 +1,101 @@ +-- Additional Plugins +lvim.plugins = { + { "wakatime/vim-wakatime" }, + + -- LSP + { + -- Tree-like view for symbols in current file using LSP + "simrat39/symbols-outline.nvim", + config = function() + require("symbols-outline").setup { + width = 18, + autofold_depth = 1, + } + end, + }, + { + -- Show function signature while typing + "ray-x/lsp_signature.nvim", + config = function() + require("lsp_signature").on_attach() + end, + event = "BufRead", + }, + + -- User interface + { + -- Code minimap for easy orientation in a longer file + "wfxr/minimap.vim", + run = "cargo install --locked code-minimap", + config = function() + vim.cmd "let g:minimap_width = 10" + end, + }, + { + -- Integrated lf file manager + "ptzz/lf.vim", + config = function() + vim.g.lf_map_keys = 0 + end, + requires = "voldikss/vim-floaterm", + }, + + -- Github copilot for code completion + { + "zbirenbaum/copilot.lua", + event = { "VimEnter" }, + config = function() + vim.defer_fn(function() + require("copilot").setup() + end, 100) + end, + }, + { "zbirenbaum/copilot-cmp", after = { "copilot.lua", "nvim-cmp" } }, + + -- + { "jasonccox/vim-wayland-clipboard" }, + + -- Yuck.vim (eww configuration language support) + { "elkowar/yuck.vim" }, + + -- Treesitter + -- { + -- -- Colorize matching parenthesis using treesitter + -- "p00f/nvim-ts-rainbow", + -- }, + { + -- Treesitter information shown directly in neovim + "nvim-treesitter/playground", + }, + { + -- Alwats show class/function name we're in + "romgrk/nvim-treesitter-context", + config = function() + require("treesitter-context").setup { + enable = true, -- Enable this plugin (Can be enabled/disabled later via commands) + throttle = true, -- Throttles plugin updates (may improve performance) + max_lines = 0, -- How many lines the window should span. Values <= 0 mean no limit. + patterns = { -- Match patterns for TS nodes. These get wrapped to match at word boundaries. + -- For all filetypes + -- Note that setting an entry here replaces all other patterns for this entry. + -- By setting the 'default' entry below, you can control which nodes you want to + -- appear in the context window. + default = { + "class", + "function", + "method", + "while", + "for", + "if", + "switch", + "case", + }, + }, + } + end, + }, +} + +-- Register copilot as cmp source +lvim.builtin.cmp.formatting.source_names["copilot"] = "(Copilot)" +table.insert(lvim.builtin.cmp.sources, 1, { name = "copilot" }) diff --git a/home/.config/lvim/lua/user/treesitter.lua b/home/.config/lvim/lua/user/treesitter.lua new file mode 100644 index 0000000..804e7e5 --- /dev/null +++ b/home/.config/lvim/lua/user/treesitter.lua @@ -0,0 +1,42 @@ +-- if you don't want all the parsers change this to a table of the ones you want +lvim.builtin.treesitter.ensure_installed = { + "bash", + "c", + "javascript", + "json", + "lua", + "python", + "typescript", + "tsx", + "css", + "rust", + "java", + "yaml", +} + +lvim.builtin.treesitter.ignore_install = {} +lvim.builtin.treesitter.highlight.enabled = true +-- lvim.builtin.treesitter.rainbow.enable = true + +local parser_config = require "nvim-treesitter.parsers".get_parser_configs() +parser_config.apparmor = { + install_info = { + url = "~/Personal/Programming/GitHub/Other/tree-sitter-apparmor", -- local path or git repo + files = {"src/parser.c"}, + -- optional entries: + branch = "main", -- default branch in case of git repo if different from master + generate_requires_npm = false, -- if stand-alone parser without npm dependencies + requires_generate_from_grammar = false, -- if folder contains pre-generated src/parser.c + }, + filetype = "apparmor", -- if filetype does not match the parser name +} + +local ft_to_parser = require"nvim-treesitter.parsers".filetype_to_parsername +ft_to_parser.apparmor = "apparmor" + +-- Temporary treesitter +lvim.keys.normal_mode["gu"] = ":TSUpdate apparmor" +lvim.keys.normal_mode["gU"] = ":TSToggle apparmor" +lvim.keys.normal_mode["gt"] = ":TSPlaygroundToggle" +lvim.keys.normal_mode["gh"] = ":TSNodeUnderCursor" +lvim.keys.normal_mode["gH"] = ":TSHighlightCapturesUnderCursor" diff --git a/home/.config/lvim/plugin/packer_compiled.lua b/home/.config/lvim/plugin/packer_compiled.lua new file mode 100644 index 0000000..5a101fa --- /dev/null +++ b/home/.config/lvim/plugin/packer_compiled.lua @@ -0,0 +1,499 @@ +-- Automatically generated packer.nvim plugin loader code + +if vim.api.nvim_call_function('has', {'nvim-0.5'}) ~= 1 then + vim.api.nvim_command('echohl WarningMsg | echom "Invalid Neovim version for packer.nvim! | echohl None"') + return +end + +vim.api.nvim_command('packadd packer.nvim') + +local no_errors, error_msg = pcall(function() + +_G._packer = _G._packer or {} +_G._packer.inside_compile = true + +local time +local profile_info +local should_profile = false +if should_profile then + local hrtime = vim.loop.hrtime + profile_info = {} + time = function(chunk, start) + if start then + profile_info[chunk] = hrtime() + else + profile_info[chunk] = (hrtime() - profile_info[chunk]) / 1e6 + end + end +else + time = function(chunk, start) end +end + +local function save_profiles(threshold) + local sorted_times = {} + for chunk_name, time_taken in pairs(profile_info) do + sorted_times[#sorted_times + 1] = {chunk_name, time_taken} + end + table.sort(sorted_times, function(a, b) return a[2] > b[2] end) + local results = {} + for i, elem in ipairs(sorted_times) do + if not threshold or threshold and elem[2] > threshold then + results[i] = elem[1] .. ' took ' .. elem[2] .. 'ms' + end + end + if threshold then + table.insert(results, '(Only showing plugins that took longer than ' .. threshold .. ' ms ' .. 'to load)') + end + + _G._packer.profile_output = results +end + +time([[Luarocks path setup]], true) +local package_path_str = "/home/itsdrike/.cache/lvim/packer_hererocks/2.1.0-beta3/share/lua/5.1/?.lua;/home/itsdrike/.cache/lvim/packer_hererocks/2.1.0-beta3/share/lua/5.1/?/init.lua;/home/itsdrike/.cache/lvim/packer_hererocks/2.1.0-beta3/lib/luarocks/rocks-5.1/?.lua;/home/itsdrike/.cache/lvim/packer_hererocks/2.1.0-beta3/lib/luarocks/rocks-5.1/?/init.lua" +local install_cpath_pattern = "/home/itsdrike/.cache/lvim/packer_hererocks/2.1.0-beta3/lib/lua/5.1/?.so" +if not string.find(package.path, package_path_str, 1, true) then + package.path = package.path .. ';' .. package_path_str +end + +if not string.find(package.cpath, install_cpath_pattern, 1, true) then + package.cpath = package.cpath .. ';' .. install_cpath_pattern +end + +time([[Luarocks path setup]], false) +time([[try_loadstring definition]], true) +local function try_loadstring(s, component, name) + local success, result = pcall(loadstring(s), name, _G.packer_plugins[name]) + if not success then + vim.schedule(function() + vim.api.nvim_notify('packer.nvim: Error running ' .. component .. ' for ' .. name .. ': ' .. result, vim.log.levels.ERROR, {}) + end) + end + return result +end + +time([[try_loadstring definition]], false) +time([[Defining packer_plugins]], true) +_G.packer_plugins = { + ["Comment.nvim"] = { + config = { "\27LJ\2\n?\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\22lvim.core.comment\frequire\0" }, + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/Comment.nvim", + url = "https://github.com/numToStr/Comment.nvim" + }, + ["FixCursorHold.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/FixCursorHold.nvim", + url = "https://github.com/antoinemadec/FixCursorHold.nvim" + }, + LuaSnip = { + config = { "\27LJ\2\n\3\0\0\v\0\23\00166\0\0\0'\2\1\0B\0\2\0024\1\0\0006\2\2\0009\2\3\0029\2\4\0029\2\5\0029\2\6\2\15\0\2\0X\3\f\21\2\1\0\22\2\0\0029\3\a\0006\5\b\0B\5\1\2'\6\t\0'\a\n\0'\b\v\0'\t\f\0'\n\r\0B\3\a\2<\3\2\0019\2\a\0006\4\14\0B\4\1\2'\5\15\0B\2\3\0029\3\16\0\18\5\2\0B\3\2\2\15\0\3\0X\4\3\21\3\1\0\22\3\0\3<\2\3\0016\3\0\0'\5\17\0B\3\2\0029\3\18\3B\3\1\0016\3\0\0'\5\19\0B\3\2\0029\3\18\0035\5\20\0=\1\21\5B\3\2\0016\3\0\0'\5\22\0B\3\2\0029\3\18\3B\3\1\1K\0\1\0\"luasnip.loaders.from_snipmate\npaths\1\0\0 luasnip.loaders.from_vscode\14lazy_load\29luasnip.loaders.from_lua\17is_directory\rsnippets\19get_config_dir\22friendly-snippets\nstart\vpacker\tpack\tsite\20get_runtime_dir\15join_paths\22friendly_snippets\fsources\fluasnip\fbuiltin\tlvim\15lvim.utils\frequire\2\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/LuaSnip", + url = "https://github.com/L3MON4D3/LuaSnip" + }, + ["alpha-nvim"] = { + config = { "\27LJ\2\n=\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\20lvim.core.alpha\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/alpha-nvim", + url = "https://github.com/goolord/alpha-nvim" + }, + ["bufferline.nvim"] = { + config = { "\27LJ\2\nB\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\25lvim.core.bufferline\frequire\0" }, + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/bufferline.nvim", + url = "https://github.com/akinsho/bufferline.nvim" + }, + ["cmp-buffer"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/cmp-buffer", + url = "https://github.com/hrsh7th/cmp-buffer" + }, + ["cmp-nvim-lsp"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/cmp-nvim-lsp", + url = "https://github.com/hrsh7th/cmp-nvim-lsp" + }, + ["cmp-path"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/cmp-path", + url = "https://github.com/hrsh7th/cmp-path" + }, + cmp_luasnip = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/cmp_luasnip", + url = "https://github.com/saadparwaiz1/cmp_luasnip" + }, + ["copilot-cmp"] = { + load_after = { + ["copilot.lua"] = true + }, + loaded = false, + needs_bufread = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/copilot-cmp", + url = "https://github.com/zbirenbaum/copilot-cmp" + }, + ["copilot.lua"] = { + after = { "copilot-cmp" }, + config = { "\27LJ\2\n5\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\fcopilot\frequire-\1\0\4\0\3\0\0066\0\0\0009\0\1\0003\2\2\0)\3d\0B\0\3\1K\0\1\0\0\rdefer_fn\bvim\0" }, + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/copilot.lua", + url = "https://github.com/zbirenbaum/copilot.lua" + }, + ["dap-buddy.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/dap-buddy.nvim", + url = "https://github.com/Pocco81/dap-buddy.nvim" + }, + ["friendly-snippets"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/friendly-snippets", + url = "https://github.com/rafamadriz/friendly-snippets" + }, + ["gitsigns.nvim"] = { + config = { "\27LJ\2\n@\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\23lvim.core.gitsigns\frequire\0" }, + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/gitsigns.nvim", + url = "https://github.com/lewis6991/gitsigns.nvim" + }, + ["lf.vim"] = { + config = { "\27LJ\2\n-\0\0\2\0\3\0\0056\0\0\0009\0\1\0)\1\0\0=\1\2\0K\0\1\0\16lf_map_keys\6g\bvim\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/lf.vim", + url = "https://github.com/ptzz/lf.vim" + }, + ["lsp_signature.nvim"] = { + config = { "\27LJ\2\n?\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\14on_attach\18lsp_signature\frequire\0" }, + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/lsp_signature.nvim", + url = "https://github.com/ray-x/lsp_signature.nvim" + }, + ["lua-dev.nvim"] = { + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/lua-dev.nvim", + url = "https://github.com/folke/lua-dev.nvim" + }, + ["lualine.nvim"] = { + config = { "\27LJ\2\n?\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\22lvim.core.lualine\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/lualine.nvim", + url = "https://github.com/nvim-lualine/lualine.nvim" + }, + ["mason-lspconfig.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/mason-lspconfig.nvim", + url = "https://github.com/williamboman/mason-lspconfig.nvim" + }, + ["mason.nvim"] = { + config = { "\27LJ\2\n=\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\20lvim.core.mason\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/mason.nvim", + url = "https://github.com/williamboman/mason.nvim" + }, + ["minimap.vim"] = { + config = { "\27LJ\2\n<\0\0\3\0\3\0\0056\0\0\0009\0\1\0'\2\2\0B\0\2\1K\0\1\0\29let g:minimap_width = 10\bcmd\bvim\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/minimap.vim", + url = "https://github.com/wfxr/minimap.vim" + }, + ["nlsp-settings.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nlsp-settings.nvim", + url = "https://github.com/tamago324/nlsp-settings.nvim" + }, + ["null-ls.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/null-ls.nvim", + url = "https://github.com/jose-elias-alvarez/null-ls.nvim" + }, + ["nvim-autopairs"] = { + config = { "\27LJ\2\nA\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\24lvim.core.autopairs\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-autopairs", + url = "https://github.com/windwp/nvim-autopairs" + }, + ["nvim-cmp"] = { + after = { "copilot-cmp" }, + config = { "\27LJ\2\n`\0\0\3\0\6\0\v6\0\0\0009\0\1\0009\0\2\0\15\0\0\0X\1\56\0\3\0'\2\4\0B\0\2\0029\0\5\0B\0\1\1K\0\1\0\nsetup\18lvim.core.cmp\frequire\bcmp\fbuiltin\tlvim\0" }, + loaded = true, + only_config = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-cmp", + url = "https://github.com/hrsh7th/nvim-cmp" + }, + ["nvim-dap"] = { + config = { "\27LJ\2\n;\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\18lvim.core.dap\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-dap", + url = "https://github.com/mfussenegger/nvim-dap" + }, + ["nvim-lspconfig"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-lspconfig", + url = "https://github.com/neovim/nvim-lspconfig" + }, + ["nvim-notify"] = { + config = { "\27LJ\2\n>\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\21lvim.core.notify\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-notify", + url = "https://github.com/rcarriga/nvim-notify" + }, + ["nvim-tree.lua"] = { + config = { "\27LJ\2\n@\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\23lvim.core.nvimtree\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-tree.lua", + url = "https://github.com/kyazdani42/nvim-tree.lua" + }, + ["nvim-treesitter"] = { + config = { "\27LJ\2\nB\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\25lvim.core.treesitter\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-treesitter", + url = "https://github.com/nvim-treesitter/nvim-treesitter" + }, + ["nvim-treesitter-context"] = { + config = { "\27LJ\2\n\1\0\0\5\0\b\0\v6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0005\3\5\0005\4\4\0=\4\6\3=\3\a\2B\0\2\1K\0\1\0\rpatterns\fdefault\1\0\0\1\t\0\0\nclass\rfunction\vmethod\nwhile\bfor\aif\vswitch\tcase\1\0\3\rthrottle\2\venable\2\14max_lines\3\0\nsetup\23treesitter-context\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-treesitter-context", + url = "https://github.com/romgrk/nvim-treesitter-context" + }, + ["nvim-ts-context-commentstring"] = { + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/nvim-ts-context-commentstring", + url = "https://github.com/JoosepAlviste/nvim-ts-context-commentstring" + }, + ["nvim-web-devicons"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/nvim-web-devicons", + url = "https://github.com/kyazdani42/nvim-web-devicons" + }, + ["onedarker.nvim"] = { + config = { "\27LJ\2\n\1\0\0\3\0\t\0\0196\0\0\0\15\0\0\0X\1\156\0\0\0009\0\1\0\a\0\2\0X\0\v6\0\3\0'\2\2\0B\0\2\0029\0\4\0B\0\1\0016\0\0\0009\0\5\0009\0\6\0009\0\a\0'\1\2\0=\1\b\0K\0\1\0\ntheme\foptions\flualine\fbuiltin\nsetup\frequire\14onedarker\16colorscheme\tlvim\30\1\0\3\0\2\0\0046\0\0\0003\2\1\0B\0\2\1K\0\1\0\0\npcall\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/onedarker.nvim", + url = "https://github.com/lunarvim/onedarker.nvim" + }, + ["packer.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/packer.nvim", + url = "https://github.com/wbthomason/packer.nvim" + }, + playground = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/playground", + url = "https://github.com/nvim-treesitter/playground" + }, + ["plenary.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/plenary.nvim", + url = "https://github.com/nvim-lua/plenary.nvim" + }, + ["popup.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/popup.nvim", + url = "https://github.com/nvim-lua/popup.nvim" + }, + ["project.nvim"] = { + config = { "\27LJ\2\n?\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\22lvim.core.project\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/project.nvim", + url = "https://github.com/ahmedkhalf/project.nvim" + }, + ["schemastore.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/schemastore.nvim", + url = "https://github.com/b0o/schemastore.nvim" + }, + ["structlog.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/structlog.nvim", + url = "https://github.com/Tastyep/structlog.nvim" + }, + ["symbols-outline.nvim"] = { + config = { "\27LJ\2\n]\0\0\3\0\4\0\a6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0B\0\2\1K\0\1\0\1\0\2\nwidth\3\18\19autofold_depth\3\1\nsetup\20symbols-outline\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/symbols-outline.nvim", + url = "https://github.com/simrat39/symbols-outline.nvim" + }, + ["telescope-fzf-native.nvim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/telescope-fzf-native.nvim", + url = "https://github.com/nvim-telescope/telescope-fzf-native.nvim" + }, + ["telescope.nvim"] = { + config = { "\27LJ\2\nA\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\24lvim.core.telescope\frequire\0" }, + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/telescope.nvim", + url = "https://github.com/nvim-telescope/telescope.nvim" + }, + ["toggleterm.nvim"] = { + config = { "\27LJ\2\n@\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\23lvim.core.terminal\frequire\0" }, + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/toggleterm.nvim", + url = "https://github.com/akinsho/toggleterm.nvim" + }, + ["vim-floaterm"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/vim-floaterm", + url = "https://github.com/voldikss/vim-floaterm" + }, + ["vim-wakatime"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/vim-wakatime", + url = "https://github.com/wakatime/vim-wakatime" + }, + ["vim-wayland-clipboard"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/vim-wayland-clipboard", + url = "https://github.com/jasonccox/vim-wayland-clipboard" + }, + ["which-key.nvim"] = { + config = { "\27LJ\2\nA\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\24lvim.core.which-key\frequire\0" }, + loaded = false, + needs_bufread = false, + only_cond = false, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/opt/which-key.nvim", + url = "https://github.com/folke/which-key.nvim" + }, + ["yuck.vim"] = { + loaded = true, + path = "/home/itsdrike/.local/share/lunarvim/site/pack/packer/start/yuck.vim", + url = "https://github.com/elkowar/yuck.vim" + } +} + +time([[Defining packer_plugins]], false) +local module_lazy_loads = { + ["^lua%-dev"] = "lua-dev.nvim" +} +local lazy_load_called = {['packer.load'] = true} +local function lazy_load_module(module_name) + local to_load = {} + if lazy_load_called[module_name] then return nil end + lazy_load_called[module_name] = true + for module_pat, plugin_name in pairs(module_lazy_loads) do + if not _G.packer_plugins[plugin_name].loaded and string.match(module_name, module_pat) then + to_load[#to_load + 1] = plugin_name + end + end + + if #to_load > 0 then + require('packer.load')(to_load, {module = module_name}, _G.packer_plugins) + local loaded_mod = package.loaded[module_name] + if loaded_mod then + return function(modname) return loaded_mod end + end + end +end + +if not vim.g.packer_custom_loader_enabled then + table.insert(package.loaders, 1, lazy_load_module) + vim.g.packer_custom_loader_enabled = true +end + +-- Config for: telescope.nvim +time([[Config for telescope.nvim]], true) +try_loadstring("\27LJ\2\nA\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\24lvim.core.telescope\frequire\0", "config", "telescope.nvim") +time([[Config for telescope.nvim]], false) +-- Config for: nvim-cmp +time([[Config for nvim-cmp]], true) +try_loadstring("\27LJ\2\n`\0\0\3\0\6\0\v6\0\0\0009\0\1\0009\0\2\0\15\0\0\0X\1\56\0\3\0'\2\4\0B\0\2\0029\0\5\0B\0\1\1K\0\1\0\nsetup\18lvim.core.cmp\frequire\bcmp\fbuiltin\tlvim\0", "config", "nvim-cmp") +time([[Config for nvim-cmp]], false) +-- Config for: minimap.vim +time([[Config for minimap.vim]], true) +try_loadstring("\27LJ\2\n<\0\0\3\0\3\0\0056\0\0\0009\0\1\0'\2\2\0B\0\2\1K\0\1\0\29let g:minimap_width = 10\bcmd\bvim\0", "config", "minimap.vim") +time([[Config for minimap.vim]], false) +-- Config for: onedarker.nvim +time([[Config for onedarker.nvim]], true) +try_loadstring("\27LJ\2\n\1\0\0\3\0\t\0\0196\0\0\0\15\0\0\0X\1\156\0\0\0009\0\1\0\a\0\2\0X\0\v6\0\3\0'\2\2\0B\0\2\0029\0\4\0B\0\1\0016\0\0\0009\0\5\0009\0\6\0009\0\a\0'\1\2\0=\1\b\0K\0\1\0\ntheme\foptions\flualine\fbuiltin\nsetup\frequire\14onedarker\16colorscheme\tlvim\30\1\0\3\0\2\0\0046\0\0\0003\2\1\0B\0\2\1K\0\1\0\0\npcall\0", "config", "onedarker.nvim") +time([[Config for onedarker.nvim]], false) +-- Config for: nvim-dap +time([[Config for nvim-dap]], true) +try_loadstring("\27LJ\2\n;\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\18lvim.core.dap\frequire\0", "config", "nvim-dap") +time([[Config for nvim-dap]], false) +-- Config for: nvim-treesitter +time([[Config for nvim-treesitter]], true) +try_loadstring("\27LJ\2\nB\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\25lvim.core.treesitter\frequire\0", "config", "nvim-treesitter") +time([[Config for nvim-treesitter]], false) +-- Config for: nvim-treesitter-context +time([[Config for nvim-treesitter-context]], true) +try_loadstring("\27LJ\2\n\1\0\0\5\0\b\0\v6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0005\3\5\0005\4\4\0=\4\6\3=\3\a\2B\0\2\1K\0\1\0\rpatterns\fdefault\1\0\0\1\t\0\0\nclass\rfunction\vmethod\nwhile\bfor\aif\vswitch\tcase\1\0\3\rthrottle\2\venable\2\14max_lines\3\0\nsetup\23treesitter-context\frequire\0", "config", "nvim-treesitter-context") +time([[Config for nvim-treesitter-context]], false) +-- Config for: lf.vim +time([[Config for lf.vim]], true) +try_loadstring("\27LJ\2\n-\0\0\2\0\3\0\0056\0\0\0009\0\1\0)\1\0\0=\1\2\0K\0\1\0\16lf_map_keys\6g\bvim\0", "config", "lf.vim") +time([[Config for lf.vim]], false) +-- Config for: alpha-nvim +time([[Config for alpha-nvim]], true) +try_loadstring("\27LJ\2\n=\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\20lvim.core.alpha\frequire\0", "config", "alpha-nvim") +time([[Config for alpha-nvim]], false) +-- Config for: nvim-notify +time([[Config for nvim-notify]], true) +try_loadstring("\27LJ\2\n>\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\21lvim.core.notify\frequire\0", "config", "nvim-notify") +time([[Config for nvim-notify]], false) +-- Config for: lualine.nvim +time([[Config for lualine.nvim]], true) +try_loadstring("\27LJ\2\n?\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\22lvim.core.lualine\frequire\0", "config", "lualine.nvim") +time([[Config for lualine.nvim]], false) +-- Config for: project.nvim +time([[Config for project.nvim]], true) +try_loadstring("\27LJ\2\n?\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\22lvim.core.project\frequire\0", "config", "project.nvim") +time([[Config for project.nvim]], false) +-- Config for: nvim-tree.lua +time([[Config for nvim-tree.lua]], true) +try_loadstring("\27LJ\2\n@\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\23lvim.core.nvimtree\frequire\0", "config", "nvim-tree.lua") +time([[Config for nvim-tree.lua]], false) +-- Config for: LuaSnip +time([[Config for LuaSnip]], true) +try_loadstring("\27LJ\2\n\3\0\0\v\0\23\00166\0\0\0'\2\1\0B\0\2\0024\1\0\0006\2\2\0009\2\3\0029\2\4\0029\2\5\0029\2\6\2\15\0\2\0X\3\f\21\2\1\0\22\2\0\0029\3\a\0006\5\b\0B\5\1\2'\6\t\0'\a\n\0'\b\v\0'\t\f\0'\n\r\0B\3\a\2<\3\2\0019\2\a\0006\4\14\0B\4\1\2'\5\15\0B\2\3\0029\3\16\0\18\5\2\0B\3\2\2\15\0\3\0X\4\3\21\3\1\0\22\3\0\3<\2\3\0016\3\0\0'\5\17\0B\3\2\0029\3\18\3B\3\1\0016\3\0\0'\5\19\0B\3\2\0029\3\18\0035\5\20\0=\1\21\5B\3\2\0016\3\0\0'\5\22\0B\3\2\0029\3\18\3B\3\1\1K\0\1\0\"luasnip.loaders.from_snipmate\npaths\1\0\0 luasnip.loaders.from_vscode\14lazy_load\29luasnip.loaders.from_lua\17is_directory\rsnippets\19get_config_dir\22friendly-snippets\nstart\vpacker\tpack\tsite\20get_runtime_dir\15join_paths\22friendly_snippets\fsources\fluasnip\fbuiltin\tlvim\15lvim.utils\frequire\2\0", "config", "LuaSnip") +time([[Config for LuaSnip]], false) +-- Config for: mason.nvim +time([[Config for mason.nvim]], true) +try_loadstring("\27LJ\2\n=\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\20lvim.core.mason\frequire\0", "config", "mason.nvim") +time([[Config for mason.nvim]], false) +-- Config for: nvim-autopairs +time([[Config for nvim-autopairs]], true) +try_loadstring("\27LJ\2\nA\0\0\3\0\3\0\0066\0\0\0'\2\1\0B\0\2\0029\0\2\0B\0\1\1K\0\1\0\nsetup\24lvim.core.autopairs\frequire\0", "config", "nvim-autopairs") +time([[Config for nvim-autopairs]], false) +-- Config for: symbols-outline.nvim +time([[Config for symbols-outline.nvim]], true) +try_loadstring("\27LJ\2\n]\0\0\3\0\4\0\a6\0\0\0'\2\1\0B\0\2\0029\0\2\0005\2\3\0B\0\2\1K\0\1\0\1\0\2\nwidth\3\18\19autofold_depth\3\1\nsetup\20symbols-outline\frequire\0", "config", "symbols-outline.nvim") +time([[Config for symbols-outline.nvim]], false) +vim.cmd [[augroup packer_load_aucmds]] +vim.cmd [[au!]] + -- Event lazy-loads +time([[Defining lazy-load event autocommands]], true) +vim.cmd [[au VimEnter * ++once lua require("packer.load")({'copilot.lua'}, { event = "VimEnter *" }, _G.packer_plugins)]] +vim.cmd [[au BufWinEnter * ++once lua require("packer.load")({'which-key.nvim', 'bufferline.nvim', 'toggleterm.nvim'}, { event = "BufWinEnter *" }, _G.packer_plugins)]] +vim.cmd [[au BufReadPost * ++once lua require("packer.load")({'nvim-ts-context-commentstring'}, { event = "BufReadPost *" }, _G.packer_plugins)]] +vim.cmd [[au BufRead * ++once lua require("packer.load")({'gitsigns.nvim', 'lsp_signature.nvim', 'Comment.nvim'}, { event = "BufRead *" }, _G.packer_plugins)]] +time([[Defining lazy-load event autocommands]], false) +vim.cmd("augroup END") + +_G._packer.inside_compile = false +if _G._packer.needs_bufread == true then + vim.cmd("doautocmd BufRead") +end +_G._packer.needs_bufread = false + +if should_profile then save_profiles() end + +end) + +if not no_errors then + error_msg = error_msg:gsub('"', '\\"') + vim.api.nvim_command('echohl ErrorMsg | echom "Error in packer_compiled: '..error_msg..'" | echom "Please check your config for correctness" | echohl None') +end diff --git a/home/.config/lvim/snippets/package.json b/home/.config/lvim/snippets/package.json new file mode 100644 index 0000000..5ff827f --- /dev/null +++ b/home/.config/lvim/snippets/package.json @@ -0,0 +1,15 @@ +{ + "name": "nvim-snippets", + "author": "ItsDrike", + "engines": { + "vscode": "^1.11.0" + }, + "contributes": { + "snippets": [ + { + "language": "python", + "path": "./python.json" + } + ] + } +} diff --git a/home/.config/lvim/snippets/python.json b/home/.config/lvim/snippets/python.json new file mode 100644 index 0000000..680c8a1 --- /dev/null +++ b/home/.config/lvim/snippets/python.json @@ -0,0 +1,21 @@ +{ + "future.__annotations__": { + "prefix": "futann", + "body": "from __future__ import annotations\n", + "description": "Add __future__.annoations import." + }, + "script": { + "prefix": "script", + "body": [ + "#!/usr/bin/env python3", + "", + "def main() -> None:", + "\t${1:...}", + "", + "", + "if __name__ == \"__main__\":", + "\tmain()" + ], + "description": "print Hello, World!" + } +} diff --git a/home/.config/lvim/spell/en.utf-8.add b/home/.config/lvim/spell/en.utf-8.add new file mode 100644 index 0000000..e63c2e3 --- /dev/null +++ b/home/.config/lvim/spell/en.utf-8.add @@ -0,0 +1,24 @@ +Flake8 +Isort +linter +flake8 +isort +TOML +YAML +linters +MyPy +Pyright +pyright +VSCode +Pylance +Docstrings +Docstring +docstrings +docstring +BSPWM +Xmonad +deserialized +serializable +ItsDrike +itsdrike +protonmail diff --git a/home/.config/lvim/spell/en.utf-8.add.spl b/home/.config/lvim/spell/en.utf-8.add.spl new file mode 100644 index 0000000..107bdb0 Binary files /dev/null and b/home/.config/lvim/spell/en.utf-8.add.spl differ diff --git a/home/.config/lvim/syntax/apparmor.vim b/home/.config/lvim/syntax/apparmor.vim new file mode 100644 index 0000000..428ce96 --- /dev/null +++ b/home/.config/lvim/syntax/apparmor.vim @@ -0,0 +1,283 @@ +" generated from apparmor.vim.in by create-apparmor.vim.py +" do not edit this file - edit apparmor.vim.in or create-apparmor.vim.py instead + +" ---------------------------------------------------------------------- +" Copyright (c) 2005 Novell, Inc. All Rights Reserved. +" Copyright (c) 2006-2012 Christian Boltz. All Rights Reserved. +" +" This program is free software; you can redistribute it and/or +" modify it under the terms of version 2 of the GNU General Public +" License as published by the Free Software Foundation. +" +" 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, contact Novell, Inc. +" +" To contact Novell about this file by physical or electronic mail, +" you may find current contact information at www.novell.com. +" +" To contact Christian Boltz about this file by physical or electronic +" mail, you may find current contact information at www.cboltz.de/en/kontakt. +" +" If you want to report a bug via bugzilla.novell.com, please assign it +" to suse-beta[AT]cboltz.de (replace [AT] with @). +" ---------------------------------------------------------------------- +" +" stick this file into ~/.vim/syntax/ and add these commands into your .vimrc +" to have vim automagically use this syntax file for these directories: +" +" autocmd BufNewFile,BufRead /etc/apparmor.d/* set syntax=apparmor +" autocmd BufNewFile,BufRead /usr/share/apparmor/extra-profiles/* set syntax=apparmor + +" profiles are case sensitive +syntax case match + +" color setup... + +" adjust colors according to the background + +" switching colors depending on the background color doesn't work +" unfortunately, so we use colors that work with light and dark background. +" Patches welcome ;-) + +"if &background == "light" +" light background + hi sdProfileName ctermfg=lightblue + hi sdHatName ctermfg=darkblue + hi sdExtHat ctermfg=darkblue +" hi sdComment2 ctermfg=darkblue + hi sdGlob ctermfg=darkmagenta + hi sdAlias ctermfg=darkmagenta + hi sdEntryWriteExec ctermfg=black ctermbg=yellow + hi sdEntryUX ctermfg=darkred cterm=underline + hi sdEntryUXe ctermfg=darkred + hi sdEntryIX ctermfg=darkcyan + hi sdEntryM ctermfg=darkcyan + hi sdEntryPX ctermfg=darkgreen cterm=underline + hi sdEntryPXe ctermfg=darkgreen + hi sdEntryW ctermfg=darkyellow + hi sdCap ctermfg=lightblue + hi sdSetCap ctermfg=black ctermbg=yellow + hi sdNetwork ctermfg=lightblue + hi sdNetworkDanger ctermfg=darkred + hi sdCapKey cterm=underline ctermfg=lightblue + hi sdCapDanger ctermfg=darkred + hi sdRLimit ctermfg=lightblue + hi def link sdEntryR Normal + hi def link sdEntryK Normal + hi def link sdFlags Normal + hi sdEntryChangeProfile ctermfg=darkgreen cterm=underline +"else +" dark background +" hi sdProfileName ctermfg=white +" hi sdHatName ctermfg=white +" hi sdGlob ctermfg=magenta +" hi sdEntryWriteExec ctermfg=black ctermbg=yellow +" hi sdEntryUX ctermfg=red cterm=underline +" hi sdEntryUXe ctermfg=red +" hi sdEntryIX ctermfg=cyan +" hi sdEntryM ctermfg=cyan +" hi sdEntryPX ctermfg=green cterm=underline +" hi sdEntryPXe ctermfg=green +" hi sdEntryW ctermfg=yellow +" hi sdCap ctermfg=lightblue +" hi sdCapKey cterm=underline ctermfg=lightblue +" hi def link sdEntryR Normal +" hi def link sdFlags Normal +" hi sdCapDanger ctermfg=red +"endif + +hi def link sdInclude Include +high def link sdComment Comment +"high def link sdComment2 Comment +high def link sdFlagKey TODO +high def link sdError ErrorMsg + + +" always sync from the start. should be relatively quick since we don't have +" that many rules and profiles shouldn't be _extremely_ large... +syn sync fromstart + +syn keyword sdFlagKey complain debug + +" highlight invalid syntax +syn match sdError /{/ contained +syn match sdError /}/ +syn match sdError /^.*$/ contains=sdComment "highlight all non-valid lines as error +" TODO: do not mark lines containing only whitespace as error + +" TODO: the sdGlob pattern is not anchored with ^ and $, so it matches all lines matching ^@{...}.* +" This allows incorrect lines also and should be checked better. +" This also (accidently ;-) includes variable definitions (@{FOO}=/bar) +" TODO: make a separate pattern for variable definitions, then mark sdGlob as contained +syn match sdGlob /\v\?|\*|\{.*,.*\}|[[^\]]\+\]|\@\{[a-zA-Z][a-zA-Z0-9_]*\}/ + +syn match sdAlias /\v^alias\s+(\/|\@\{\S*\})\S*\s+-\>\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob + +" syn match sdComment /#.*/ + +syn cluster sdEntry contains=sdEntryWriteExec,sdEntryR,sdEntryW,sdEntryIX,sdEntryPX,sdEntryPXe,sdEntryUX,sdEntryUXe,sdEntryM,sdCap,sdSetCap,sdExtHat,sdRLimit,sdNetwork,sdNetworkDanger,sdEntryChangeProfile + + +" TODO: support audit and deny keywords for all rules (not only for files) +" TODO: higlight audit and deny keywords everywhere + +" Capability line + +" normal capabilities - really keep this list? syn match sdCap should be enough... (difference: sdCapKey words would loose underlining) +syn keyword sdCapKey audit_read block_suspend chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_broadcast net_raw setfcap setgid setpcap setuid syslog sys_boot sys_chroot sys_nice sys_pacct sys_ptrace sys_resource sys_time sys_tty_config wake_alarm + +" dangerous capabilities - highlighted separately +syn keyword sdCapDanger audit_control audit_write mac_override mac_admin set_fcap sys_admin sys_module sys_rawio + +" full line. Keywords are from sdCapKey + sdCapDanger +syn match sdCap /\v^\s*(audit\s+)?(deny\s+|allow\s+)?capability\s+((audit_control|audit_read|audit_write|block_suspend|chown|dac_override|dac_read_search|fowner|fsetid|ipc_lock|ipc_owner|kill|lease|linux_immutable|mac_admin|mac_override|mknod|net_admin|net_bind_service|net_broadcast|net_raw|setfcap|setgid|setpcap|setuid|syslog|sys_admin|sys_boot|sys_chroot|sys_module|sys_nice|sys_pacct|sys_ptrace|sys_rawio|sys_resource|sys_time|sys_tty_config|wake_alarm)\s+)*(audit_control|audit_read|audit_write|block_suspend|chown|dac_override|dac_read_search|fowner|fsetid|ipc_lock|ipc_owner|kill|lease|linux_immutable|mac_admin|mac_override|mknod|net_admin|net_bind_service|net_broadcast|net_raw|setfcap|setgid|setpcap|setuid|syslog|sys_admin|sys_boot|sys_chroot|sys_module|sys_nice|sys_pacct|sys_ptrace|sys_rawio|sys_resource|sys_time|sys_tty_config|wake_alarm)\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdCapKey,sdCapDanger,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +" all capabilities ('capability' without any keyword) +syn match sdCapDanger /\v^\s*(audit\s+)?(deny\s+|allow\s+)?capability\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" Network line +" Syntax: network domain (inet, ...) type (stream, ...) protocol (tcp, ...) +" TODO: 'owner' isn't supported, but will be (JJ, 2011-01-11) +syn match sdNetwork /\v^\s*(audit\s+)?(deny\s+|allow\s+)?network(\s+(unix|inet|ax25|ipx|appletalk|netrom|bridge|atmpvc|x25|inet6|rose|netbeui|security|key|netlink|packet|ash|econet|atmsvc|rds|sna|irda|pppox|wanpipe|llc|can|tipc|bluetooth|iucv|rxrpc|isdn|phonet|ieee802154|caif|alg|nfc|vsock))?(\s+(stream|dgram|seqpacket|rdm|packet))?(\s+tcp|\s+udp|\s+icmp)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +" network rules containing 'raw' +syn match sdNetworkDanger /\v^\s*(audit\s+)?(deny\s+|allow\s+)?network(\s+(unix|inet|ax25|ipx|appletalk|netrom|bridge|atmpvc|x25|inet6|rose|netbeui|security|key|netlink|packet|ash|econet|atmsvc|rds|sna|irda|pppox|wanpipe|llc|can|tipc|bluetooth|iucv|rxrpc|isdn|phonet|ieee802154|caif|alg|nfc|vsock))?(\s+(raw))(\s+tcp|\s+udp|\s+icmp)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +" 'all networking' includes raw -> mark as dangerous +syn match sdNetworkDanger /\v^\s*(audit\s+)?(deny\s+|allow\s+)?network\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + + +" Change Profile +" TODO: audit and deny support will be added (JJ, 2011-01-11) +syn match sdEntryChangeProfile /\v^\s*change_profile\s+-\>\s+\S+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + + +" rlimit +" TODO: audit and deny support will be added (JJ, 2011-01-11) +" +"syn match sdRLimit /\v^\s*rlimit\s+()\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment +syn match sdRLimit /\v^\s*set\s+rlimit\s+(nofile|ofile|nproc|rtprio)\s+\<\=\s+[0-9]+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment +syn match sdRLimit /\v^\s*set\s+rlimit\s+(locks|sigpending)\s+\<\=\s+[0-9]+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment +syn match sdRLimit /\v^\s*set\s+rlimit\s+(fsize|data|stack|core|rss|as|memlock|msgqueue)\s+\<\=\s+[0-9]+([KMG]B)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment +syn match sdRLimit /\v^\s*set\s+rlimit\s+nice\s+\<\=\s+(-1?[0-9]|-20|1?[0-9])\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment +syn match sdRLimit /\v^\s*set\s+rlimit\s+cpu\s+\<\=\s+[0-9]+(seconds|minutes|hours|days)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment +syn match sdRLimit /\v^\s*set\s+rlimit\s+rttime\s+\<\=\s+[0-9]+(ms|seconds|minutes)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment +syn match sdRLimit /\v^\s*set\s+rlimit\s+(cpu|rttime|nofile|nproc|rtprio|locks|sigpending|fsize|data|stack|core|rss|as|memlock|msgqueue|nice)\s+\<\=\s+infinity\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment + +" link rules +syn match sdEntryW /\v^\s+(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?link\s+(subset\s+)?(\/|\@\{\S*\})\S*\s+-\>\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob + + +syn match sdExtHat /\v^\s+(\^|profile\s+)\S+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdComment " hat without {...} + + + + +syn match sdProfileName /\v^((profile\s+)?\/\S+|profile\s+([a-zA-Z0-9]\S*\s)?\S+)\s+((flags\s*\=\s*)?\(\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted)(\s*,\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted))*\s*\)\s+)=\{/ contains=sdProfileStart,sdHatName,sdFlags,sdComment,sdGlob +syn match sdProfileStart /{/ contained +syn match sdProfileEnd /^}\s*(#.*)?$/ contained " TODO: syn region does not (yet?) allow usage of comment in end= + " TODO: Removing the $ mark from end= will allow non-comments also :-( +syn match sdHatName /\v^\s+(\^|profile\s+)\S+\s+((flags\s*\=\s*)?\(\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted)(\s*,\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted))*\s*\)\s+)=\{/ contains=sdProfileStart,sdFlags,sdComment +syn match sdHatStart /{/ contained +syn match sdHatEnd /}/ contained " TODO: allow comments + [same as for syn match sdProfileEnd] +syn match sdFlags /\v((flags\s*\=\s*)?\(\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted)(\s*,\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted))*\s*\)\s+)/ contained contains=sdFlagKey + +syn match sdComment /\s*#.*$/ +" NOTE: contains=sdComment changes #include highlighting to comment color. +" NOTE: Comment highlighting still works without contains=sdComment. +syn match sdInclude /\s*#include\s<\S*>/ " TODO: doesn't check until $ +syn match sdInclude /\s*include\s<\S*>/ " TODO: doesn't check until $ + +" basic profile block... +" \s+ does not work in end=, therefore using \s\s* +syn region Normal start=/\v^(profile\s+)?\S+\s+((flags\s*\=\s*)?\(\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted)(\s*,\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted))*\s*\)\s+)=\{/ matchgroup=sdProfileEnd end=/^}\s*$/ contains=sdProfileName,Hat,@sdEntry,sdComment,sdError,sdInclude +syn region Hat start=/\v^\s+(\^|profile\s+)\S+\s+((flags\s*\=\s*)?\(\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted)(\s*,\s*(complain|audit|attach_disconnected|no_attach_disconnected|chroot_attach|chroot_no_attach|chroot_relative|namespace_relative|mediate_deleted|delegate_deleted))*\s*\)\s+)=\{/ matchgroup=sdHatEnd end=/^\s\s*}\s*$/ contains=sdHatName,@sdEntry,sdComment,sdError,sdInclude + +" file permissions + + + + + +" file rules added with create_file_rule() + +" write + exec/mmap - danger! (known bug: accepts aw to keep things simple) +syn match sdEntryWriteExec /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(l|r|w|a|m|k|[iuUpPcC]x)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryWriteExec /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(l|r|w|a|m|k|[iuUpPcC]x)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryWriteExec /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(l|r|w|a|m|k|[iuUpPcC]x)+(\s+-\>\s+\S+)?\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryWriteExec /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(l|r|w|a|m|k|[iuUpPcC]x)+(\s+-\>\s+\S+)?\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" ux(mr) - unconstrained entry, flag the line red. also includes pux which is unconstrained if no profile exists +syn match sdEntryUX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(r|m|k|ux|pux)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryUX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(r|m|k|ux|pux)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryUX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|ux|pux)+(\s+-\>\s+\S+)?\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryUX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|ux|pux)+(\s+-\>\s+\S+)?\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" Ux(mr) and PUx(mr) - like ux + clean environment +syn match sdEntryUXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(r|m|k|Ux|PUx)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryUXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(r|m|k|Ux|PUx)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryUXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|Ux|PUx)+(\s+-\>\s+\S+)?\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryUXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|Ux|PUx)+(\s+-\>\s+\S+)?\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" px/cx/pix/cix(mrk) - standard exec entry, flag the line blue +syn match sdEntryPX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(r|m|k|px|cx|pix|cix)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryPX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(r|m|k|px|cx|pix|cix)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryPX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|px|cx|pix|cix)+(\s+-\>\s+\S+)?\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryPX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|px|cx|pix|cix)+(\s+-\>\s+\S+)?\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" Px/Cx/Pix/Cix(mrk) - like px/cx + clean environment +syn match sdEntryPXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(r|m|k|Px|Cx|Pix|Cix)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryPXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(r|m|k|Px|Cx|Pix|Cix)+(\s+-\>\s+\S+)?\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryPXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|Px|Cx|Pix|Cix)+(\s+-\>\s+\S+)?\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryPXe /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|Px|Cx|Pix|Cix)+(\s+-\>\s+\S+)?\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" ix(mr) - standard exec entry, flag the line green +syn match sdEntryIX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(r|m|k|ix)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryIX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(r|m|k|ix)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryIX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|ix)+\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryIX /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k|ix)+\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" mr - mmap with PROT_EXEC +syn match sdEntryM /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(r|m|k)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryM /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(r|m|k)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryM /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k)+\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryM /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(r|m|k)+\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" special case: deny x is allowed (does not need to be ix, px, ux or cx) +syn match sdEntryM /\v^\s*(audit\s+)?deny\s+(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(r|m|k|x)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryM /\v^\s*(audit\s+)?deny\s+(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(r|m|k|x)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryM /\v^\s*(audit\s+)?deny\s+(owner\s+|other\s+)?(r|m|k|x)+\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryM /\v^\s*(audit\s+)?deny\s+(owner\s+|other\s+)?(r|m|k|x)+\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" write + append is an error +syn match sdError /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+\S*(w\S*a|a\S*w)\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdError /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+\S*(w\S*a|a\S*w)\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdError /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?\S*(w\S*a|a\S*w)\S*\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdError /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?\S*(w\S*a|a\S*w)\S*\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" write entry, flag the line yellow +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(l|r|w|k)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(l|r|w|k)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(l|r|w|k)+\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(l|r|w|k)+\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" append entry, flag the line yellow +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+(l|r|a|k)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+(l|r|a|k)+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(l|r|a|k)+\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryW /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(l|r|a|k)+\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" read entry + locking, currently no highlighting +syn match sdEntryK /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+[rlk]+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryK /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+[rlk]+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryK /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?[rlk]+\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryK /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?[rlk]+\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + +" read entry, no highlighting +syn match sdEntryR /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?(\/|\@\{\S*\})\S*\s+[rl]+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryR /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?"(\/|\@\{\S*\})\S*"\s+[rl]+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryR /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?[rl]+\s+(\/|\@\{\S*\})\S*\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude +syn match sdEntryR /\v^\s*(audit\s+)?(deny\s+|allow\s+)?(owner\s+|other\s+)?[rl]+\s+"(\/|\@\{\S*\})\S*"+\s*,(\s*$|(\s*#.*$)\@=)/ contains=sdGlob,sdComment nextgroup=@sdEntry,sdComment,sdError,sdInclude + diff --git a/home/.config/lvim/syntax/apparmor.vim.bak b/home/.config/lvim/syntax/apparmor.vim.bak new file mode 120000 index 0000000..6dd60b5 --- /dev/null +++ b/home/.config/lvim/syntax/apparmor.vim.bak @@ -0,0 +1 @@ +/usr/share/vim/vimfiles/syntax/apparmor.vim \ No newline at end of file diff --git a/home/.config/mimeapps.list b/home/.config/mimeapps.list new file mode 100644 index 0000000..736dc63 --- /dev/null +++ b/home/.config/mimeapps.list @@ -0,0 +1,14 @@ + +[Default Applications] +inode/directory=pcmanfm.desktop +image/jpeg=org.nomacs.ImageLounge.desktop +image/png=org.nomacs.ImageLounge.desktop +image/gif=org.nomacs.ImageLounge.desktop +application/pdf=firefox.desktop +text/html=firefox.desktop +x-scheme-handler/http=firefox.desktop +x-scheme-handler/https=firefox.desktop +x-scheme-handler/about=firefox.desktop +x-scheme-handler-unknown=firefox.desktop +application/json=nvim.desktop +video/mp4=mpv.desktop diff --git a/home/.config/mozilla/.keep b/home/.config/mozilla/.keep new file mode 100644 index 0000000..e69de29 diff --git a/home/.config/mpv/input.conf b/home/.config/mpv/input.conf new file mode 100644 index 0000000..5ba5b69 --- /dev/null +++ b/home/.config/mpv/input.conf @@ -0,0 +1,25 @@ +# Vim keys seeking +l seek 5 +h seek -5 +j seek -60 +k seek 60 + +# Set A-B Loop key to g, since l was rebound +g ab-loop + +# Swap i and I, use lowercase for toggle +i script-binding stats/display-stats-toggle +I script-binding stats/display-stats + +# Zooming +- add video-zoom -.25 ++ add video-zoom .25 +# Moving/panning video +kp8 add video-pan-y .05 +kp6 add video-pan-x -.05 +kp2 add video-pan-y -.05 +kp4 add video-pan-x .05 +kp5 set video-pan-x 0; set video-pan-y 0; set video-zoom 0 + +# Rotation +ctrl+r cycle_values video-rotate "90" "180" "270" "0" diff --git a/home/.config/mpv/input.conf.default b/home/.config/mpv/input.conf.default new file mode 100644 index 0000000..38adf14 --- /dev/null +++ b/home/.config/mpv/input.conf.default @@ -0,0 +1,180 @@ +# mpv keybindings +# +# Location of user-defined bindings: ~/.config/mpv/input.conf +# +# Lines starting with # are comments. Use SHARP to assign the # key. +# Copy this file and uncomment and edit the bindings you want to change. +# +# List of commands and further details: DOCS/man/input.rst +# List of special keys: --input-keylist +# Keybindings testing mode: mpv --input-test --force-window --idle +# +# Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore'). +# +# Strings need to be quoted and escaped: +# KEY show-text "This is a single backslash: \\ and a quote: \" !" +# +# You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with +# the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal). +# +# The default keybindings are hardcoded into the mpv binary. +# You can disable them completely with: --no-input-default-bindings + +# Developer note: +# On compilation, this file is baked into the mpv binary, and all lines are +# uncommented (unless '#' is followed by a space) - thus this file defines the +# default key bindings. + +# If this is enabled, treat all the following bindings as default. +#default-bindings start + +#MBTN_LEFT ignore # don't do anything +#MBTN_LEFT_DBL cycle fullscreen # toggle fullscreen +#MBTN_RIGHT cycle pause # toggle pause/playback mode +#MBTN_BACK playlist-prev # skip to the previous file +#MBTN_FORWARD playlist-next # skip to the next file + +# Mouse wheels, touchpad or other input devices that have axes +# if the input devices supports precise scrolling it will also scale the +# numeric value accordingly +#WHEEL_UP seek 10 # seek 10 seconds forward +#WHEEL_DOWN seek -10 # seek 10 seconds backward +#WHEEL_LEFT add volume -2 # lower the volume +#WHEEL_RIGHT add volume 2 # raise the volume + +## Seek units are in seconds, but note that these are limited by keyframes +#RIGHT seek 5 # seek 5 seconds forward +#LEFT seek -5 # seek 5 seconds backward +#UP seek 60 # seek 1 minute forward +#DOWN seek -60 # seek 1 minute backward +# Do smaller, always exact (non-keyframe-limited), seeks with shift. +# Don't show them on the OSD (no-osd). +#Shift+RIGHT no-osd seek 1 exact # seek exactly 1 second forward +#Shift+LEFT no-osd seek -1 exact # seek exactly 1 second backward +#Shift+UP no-osd seek 5 exact # seek exactly 5 seconds forward +#Shift+DOWN no-osd seek -5 exact # seek exactly 5 seconds backward +#Ctrl+LEFT no-osd sub-seek -1 # seek to the previous subtitle +#Ctrl+RIGHT no-osd sub-seek 1 # seek to the next subtitle +#Ctrl+Shift+LEFT sub-step -1 # change subtitle timing such that the previous subtitle is displayed +#Ctrl+Shift+RIGHT sub-step 1 # change subtitle timing such that the next subtitle is displayed +#Alt+left add video-pan-x 0.1 # move the video right +#Alt+right add video-pan-x -0.1 # move the video left +#Alt+up add video-pan-y 0.1 # move the video down +#Alt+down add video-pan-y -0.1 # move the video up +#Alt++ add video-zoom 0.1 # zoom in +#Alt+- add video-zoom -0.1 # zoom out +#Alt+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0 # reset zoom and pan settings +#PGUP add chapter 1 # seek to the next chapter +#PGDWN add chapter -1 # seek to the previous chapter +#Shift+PGUP seek 600 # seek 10 minutes forward +#Shift+PGDWN seek -600 # seek 10 minutes backward +#[ multiply speed 1/1.1 # decrease the playback speed +#] multiply speed 1.1 # increase the playback speed +#{ multiply speed 0.5 # halve the playback speed +#} multiply speed 2.0 # double the playback speed +#BS set speed 1.0 # reset the speed to normal +#Shift+BS revert-seek # undo the previous (or marked) seek +#Shift+Ctrl+BS revert-seek mark # mark the position for revert-seek +#q quit # exit +#Q quit-watch-later # exit and remember the playback position +#q {encode} quit 4 # exit +#ESC set fullscreen no # leave fullscreen +#ESC {encode} quit 4 # exit +#p cycle pause # toggle pause/playback mode +#. frame-step # advance one frame and pause +#, frame-back-step # go back by one frame and pause +#SPACE cycle pause # toggle pause/playback mode +#> playlist-next # skip to the next file +#ENTER playlist-next # skip to the next file +#< playlist-prev # skip to the previous file +#O no-osd cycle-values osd-level 3 1 # toggle displaying the OSD on user interaction or always +#o show-progress # show playback progress +#P show-progress # show playback progress +#i script-binding stats/display-stats # display information and statistics +#I script-binding stats/display-stats-toggle # toggle displaying information and statistics +#` script-binding console/enable # open the console +#z add sub-delay -0.1 # shift subtitles 100 ms earlier +#Z add sub-delay +0.1 # delay subtitles by 100 ms +#x add sub-delay +0.1 # delay subtitles by 100 ms +#ctrl++ add audio-delay 0.100 # change audio/video sync by delaying the audio +#ctrl+- add audio-delay -0.100 # change audio/video sync by shifting the audio earlier +#Shift+g add sub-scale +0.1 # increase the subtitle font size +#Shift+f add sub-scale -0.1 # decrease the subtitle font size +#9 add volume -2 # lower the volume +#/ add volume -2 # lower the volume +#0 add volume 2 # raise the volume +#* add volume 2 # raise the volume +#m cycle mute # toggle mute +#1 add contrast -1 # decrease the contrast +#2 add contrast 1 # increase the contrast +#3 add brightness -1 # decrease the brightness +#4 add brightness 1 # increase the brightness +#5 add gamma -1 # decrease the gamma +#6 add gamma 1 # increase the gamma +#7 add saturation -1 # decrease the saturation +#8 add saturation 1 # increase the saturation +#Alt+0 set current-window-scale 0.5 # halve the window size +#Alt+1 set current-window-scale 1.0 # reset the window size +#Alt+2 set current-window-scale 2.0 # double the window size +#d cycle deinterlace # toggle the deinterlacing filter +#r add sub-pos -1 # move subtitles up +#R add sub-pos +1 # move subtitles down +#t add sub-pos +1 # move subtitles down +#v cycle sub-visibility # hide or show the subtitles +#Alt+v cycle secondary-sub-visibility # hide or show the secondary subtitles +#V cycle sub-ass-vsfilter-aspect-compat # toggle stretching SSA/ASS subtitles with anamorphic videos to match the historical renderer +#u cycle-values sub-ass-override "force" "no" # toggle overriding SSA/ASS subtitle styles with the normal styles +#j cycle sub # switch subtitle track +#J cycle sub down # switch subtitle track backwards +#SHARP cycle audio # switch audio track +#_ cycle video # switch video track +#T cycle ontop # toggle placing the video on top of other windows +#f cycle fullscreen # toggle fullscreen +#s screenshot # take a screenshot of the video in its original resolution with subtitles +#S screenshot video # take a screenshot of the video in its original resolution without subtitles +#Ctrl+s screenshot window # take a screenshot of the window with OSD and subtitles +#Alt+s screenshot each-frame # automatically screenshot every frame; issue this command again to stop taking screenshots +#w add panscan -0.1 # decrease panscan +#W add panscan +0.1 # shrink black bars by cropping the video +#e add panscan +0.1 # shrink black bars by cropping the video +#A cycle-values video-aspect-override "16:9" "4:3" "2.35:1" "-1" # cycle the video aspect ratio ("-1" is the container aspect) +#POWER quit # exit +#PLAY cycle pause # toggle pause/playback mode +#PAUSE cycle pause # toggle pause/playback mode +#PLAYPAUSE cycle pause # toggle pause/playback mode +#PLAYONLY set pause no # unpause +#PAUSEONLY set pause yes # pause +#STOP quit # exit +#FORWARD seek 60 # seek 1 minute forward +#REWIND seek -60 # seek 1 minute backward +#NEXT playlist-next # skip to the next file +#PREV playlist-prev # skip to the previous file +#VOLUME_UP add volume 2 # raise the volume +#VOLUME_DOWN add volume -2 # lower the volume +#MUTE cycle mute # toggle mute +#CLOSE_WIN quit # exit +#CLOSE_WIN {encode} quit 4 # exit +#ctrl+w quit # exit +#E cycle edition # switch edition +#l ab-loop # set/clear A-B loop points +#L cycle-values loop-file "inf" "no" # toggle infinite looping +#ctrl+c quit 4 # exit +#DEL script-binding osc/visibility # cycle OSC visibility between never, auto (mouse-move) and always +#ctrl+h cycle-values hwdec "auto" "no" # toggle hardware decoding +#F8 show-text ${playlist} # show the playlist +#F9 show-text ${track-list} # show the list of video, audio and sub tracks + +# +# Legacy bindings (may or may not be removed in the future) +# +#! add chapter -1 # seek to the previous chapter +#@ add chapter 1 # seek to the next chapter + +# +# Not assigned by default +# (not an exhaustive list of unbound commands) +# + +# ? cycle sub-forced-only # toggle DVD forced subs +# ? stop # stop playback (quit or enter idle mode) + diff --git a/home/.config/mpv/mpv.conf b/home/.config/mpv/mpv.conf new file mode 100644 index 0000000..3c30981 --- /dev/null +++ b/home/.config/mpv/mpv.conf @@ -0,0 +1 @@ +loop=yes diff --git a/home/.config/nomacs/Image Lounge.conf b/home/.config/nomacs/Image Lounge.conf new file mode 100644 index 0000000..2fcb47a --- /dev/null +++ b/home/.config/nomacs/Image Lounge.conf @@ -0,0 +1,92 @@ +[General] +DkEditDock=2 +DkExplorer=1 +firstTime=false +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x3\xc7\0\0\x2\x38\0\0\au\0\0\x4\x32\0\0\x3\xc7\0\0\x2\x38\0\0\au\0\0\x4-\0\0\0\0\x2\0\0\0\a\x80\0\0\x3\xc7\0\0\x2\x38\0\0\au\0\0\x4\x32) +geometryNomacs=@Rect(967 568 943 507) +windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x3\0\0\0\0\0\0\x1\0\0\0\x4\x4\xfc\x2\0\0\0\x1\xfb\0\0\0\x14\0\x44\0k\0\x45\0x\0p\0l\0o\0r\0\x65\0r\0\0\0\0\x34\0\0\x4\x4\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\xdd\0\0\x3\xc4\xfc\x2\0\0\0\x1\xfb\0\0\0\x14\0\x44\0k\0\x45\0\x64\0i\0t\0\x44\0o\0\x63\0k\0\0\0\0\x1e\0\0\x3\xc4\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\a\x80\0\0\0>\xfc\x1\0\0\0\x1\xfb\0\0\0\x10\0\x63\0r\0o\0p\0\x44\0o\0\x63\0k\0\0\0\0\0\0\0\a\x80\0\0\0\0\0\0\0\0\0\0\x3\xaf\0\0\x1\xe4\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\0\0\0\x16\0\x45\0\x64\0i\0t\0T\0o\0o\0l\0\x42\0\x61\0r\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0) + +[AppSettings] +appMode=0 +currentAppMode=0 +defaultJpgQuality=97 +firstTime.nomacs.3=false +hideAllPanels=true +showPlayer=@Variant(\0\0\0\r\0\0\0\x6\0) + +[CustomPluginShortcuts] +Composite%20Image=Composite Image +Crop%20to%20Metadata=Crop to Metadata +Crop%20to%20Page=Crop to Page +Draw%20to%20Page=Draw to Page +Fake%20Miniatures=Fake Miniatures +Image%20Transform=Image Transform +Paint%20on%20Image=Paint on Image + +[DisplaySettings] +bgColorNoMacsRGBA=4281545523 +bgColorWidgetRGBA=2852126720 +fadeSec=@Variant(\0\0\0\x87\0\0\0\0) +fontColorRGBA=4292730333 +highlightColorRGBA=4278233855 +iconColorRGBA=4292730333 +iconSize=18 +showCrop=true +themeName312=Dark-Theme.css +transition=0 +zoomToFit=true + +[DkAppManager] +Apps\size=0 + +[DkCompressionDialog] +CompressionCombo0=0 +bgCompressionColor0=4294967295 + +[DkDialog] +deleteFileDialog=false +deleteFileDialog-answer=16384 +overwriteDialog=false +overwriteDialog-answer=16384 +saveEditDialog=false +saveEditDialog-answer=16384 +saveTabsDialog=false +saveTabsDialog-answer=65536 + +[DkExplorer] +Date%20ModifiedHidden=true +Date%20ModifiedSize=0 +LoadSelected=false +NameHidden=false +NameSize=254 +ReadOnly=true +RootPath=/home/itsdrike +SizeHidden=true +SizeSize=0 +TypeHidden=true +TypeSize=0 + +[DkFilePreview] +windowPosition=1 + +[DkMetaDataHUD] +keyValues=File.Filename, File.Path, File.Size, Exif.Image.Make, Exif.Image.Model, Exif.Image.DateTime, Exif.Image.ImageDescription, Exif.Photo.ISO, Exif.Photo.FocalLength, Exif.Photo.ExposureTime, Exif.Photo.Flash, Exif.Photo.FNumber +numColumns=-1 +windowPosition=3 + +[MetaDataSettings] +saveExifOrientation=false + +[Page%20Extraction%20Plugin] +Method=0 + +[SlideShowSettings] +time=@Variant(\0\0\0\x87@\xa0\0\0) + +[SynchronizeSettings] +checkForUpdates=true +disableUpdateInteraction=false + +[zooming] +useLevels=false +zoomLevels="0.0001,0.001,0.01,0.05,0.1,0.125,0.166,0.25,0.333,0.5,0.66,1,1.5,2,3,4,5,6,7,8,12,16,32,64,128" diff --git a/home/.config/npm/npmrc b/home/.config/npm/npmrc new file mode 100644 index 0000000..fc84b78 --- /dev/null +++ b/home/.config/npm/npmrc @@ -0,0 +1,4 @@ +prefix=${XDG_DATA_HOME}/npm +cache=${XDG_CACHE_HOME}/npm +tmp=${XDG_RUNTIME_DIR}/npm +init-module=${XDG_CONFIG_HOME}/npm/config/npm-init.js diff --git a/home/.config/pcmanfm/default/pcmanfm.conf b/home/.config/pcmanfm/default/pcmanfm.conf new file mode 100644 index 0000000..e3ca37a --- /dev/null +++ b/home/.config/pcmanfm/default/pcmanfm.conf @@ -0,0 +1,29 @@ +[config] +bm_open_method=0 + +[volume] +mount_on_startup=1 +mount_removable=1 +autorun=1 + +[autorun] +x-content/bootable-media=pcmanfm + +[ui] +always_show_tabs=0 +max_tab_chars=32 +win_width=943 +win_height=502 +splitter_pos=217 +media_in_new_tab=0 +desktop_folder_new_win=0 +change_tab_on_drop=1 +close_on_unmount=1 +focus_previous=0 +side_pane_mode=places +view_mode=icon +show_hidden=0 +sort=desc;ascending; +toolbar=newtab;navigation;home; +show_statusbar=1 +pathbar_mode_buttons=1 diff --git a/home/.config/pki/.keep b/home/.config/pki/.keep new file mode 100644 index 0000000..e69de29 diff --git a/home/.config/pypoetry/config.toml b/home/.config/pypoetry/config.toml new file mode 100644 index 0000000..5fcef8c --- /dev/null +++ b/home/.config/pypoetry/config.toml @@ -0,0 +1,3 @@ +[virtualenvs] +in-project = true +prefer-active-python = true diff --git a/home/.config/shell/aliases b/home/.config/shell/aliases new file mode 100755 index 0000000..d923be9 --- /dev/null +++ b/home/.config/shell/aliases @@ -0,0 +1,298 @@ +#!/bin/sh + +# I'm not the greatest typist +alias sl='ls' +alias mdkir='mkdir' +alias soruce='source' +alias souce='source' +alias suod='sudo ' +alias sduo='sudo ' + +# Replacements (adding flags) +alias cp='cp -iv' # Ask before overwriting, verbose +alias mv='mv -iv' # Ask before overwriting, verbose +alias rm='trash-put' # Use trash-cli instead of true removal +alias rmr='\rm -v' # True rm, verbose (asking here is too annoying) +alias wget='wget -c' # Resume wget by default +alias df='df -H' # Show sizes as powers of 1000 + +# Directory changing +alias ..='cd ..' +alias ...='cd ../../' +alias ....='cd ../../../' +alias .....='cd ../../../../' +alias .2='cd ../../' +alias .3='cd ../../../' +alias .4='cd ../../../../' +alias .5='cd ../../../../../' + +# Files/Directories utilities +alias mkdir='mkdir -p' +alias md='mkdir' +alias fhere='find . -name' +alias rr='rmr -r' +alias rf='rmr -f' +alias rrf='rmr -rf' +alias vimdiff='nvim -d' + +# Directory listing aliases, defaults to exa, if aviable +if command -v exa > /dev/null; then + alias ls='exa' + alias l='exa -glah --classify' + alias ll='exa -glah --classify -s=size --group-directories-first -r' + alias ldir='exa -glahD' + alias tree='exa -Tlagh' + alias dotall='exa -hulad .[a-z]*' # Show both dotdirs and dotfiles + alias dotfiles='dotall | grep -v ^d' # Show all dotfiles + alias dotdirs='dotall | grep --color=never ^d' # Show all dotdirs +else + alias ls='ls --color=auto' + alias l='ls -lahX --classify' + alias ll='ls -lahX --classify --group-directories-first' + alias ldir='ls -lahX --classify | grep --color=never ^d' + alias dotall='ls -lahXd .[a-z]*' + alias dotfiles='dotall | grep -v ^d' + alias dotdirs='dotall | grep --color=never ^d' +fi + +# Config access shortcuts +alias cfzsh='vim ~/.config/zsh/.zshrc' +alias cfalias='vim ~/.config/shell/aliases' +alias cffunctions='vim ~/.config/shell/functions' +alias cfprofile='vim ~/.config/shell/profile' +alias cfenvironment='vim ~/.config/shell/environment' +alias cfenv='cfenvironment' +alias cfhandlers='vim ~/.config/shell/handlers' +alias cfprompt='vim ~/.config/shell/prompt' +alias cfkeybinds='vim ~/.config/shell/keybinds' +alias cfxprofile='vim ~/.config/x11/xprofile' +alias cfsxhkd='vim ~/.config/sxhkd/sxhkdrc' +alias cfkbd='cfsxhkd' +alias cfbspwm='vim ~/.config/bspwm/bspwmrc' +alias cfxmonad='vim ~/.config/xmonad/xmonad.hs && xmonad --recompile && xmonad --restart' +alias cfxmobar='vim ~/.config/xmobar/xmobarrc.hs && ~/.config/xmobar/multi_mon.sh 2' +alias cftodo='vim ~/Personal/vimwiki/todo.md' +alias cfnvim='vim ~/.config/nvim' +alias cfvim='cfnvim' + +# z.lua shortcuts +alias j='z' # for the sake of autojump old habits +alias zz='z -c' # restrict matches to subdirs of $PWD +alias zb='z -b' # restrict matches to parent directories +alias zi='z -I' # cd with interactive fzf selection +alias zbi='z -b -I' # pick parent directory to cd into with fzf + +# Fallbacks +command -v hd > /dev/null || alias hd='hexdump -C' # Cannonical hex dump; some systems have this symlinked +command -v md5sum > /dev/null || alias md5sum='md5' # Fallback from `md5sum` to `md5` +command -v sha1sum > /dev/null || alias sha1sum='shasum' # Fallback from `sha1sum` to `shasum` +command -v vim > /dev/null && alias vi='vim' # Let vim take precedence over vi +command -v nvim > /dev/null && alias vi='nvim' && alias vim='nvim' # Let nvim take precedence over vi/vim +command -v vimtutor > /dev/null || alias vimtutor='nvim -c Tutor' # Let vimtutor fallback to nvim's tutor + +# X11 clipboard (either using xclip or xsel, xsel takes precedence if both) +command -v xclip > /dev/null && alias pbcopy='xclip -selection clipboard' +command -v xclip > /dev/null && alias pbpaste='xclip -selection clipboard -o' +command -v xsel > /dev/null && alias pbcopy='xsel --clipboard --input' +command -v xsel > /dev/null && alias pbpaste='xsel --clipboard --output' + +# File validation and manipulation +alias yamlcheck='python -c "import sys, yaml as y; y.safe_load(open(sys.argv[1]))"' # Validate YAML +alias jsoncheck='jq "." >/dev/null <' # Validate JSON +alias urlencode='python2 -c "import sys, urllib as ul; print ul.quote_plus(sys.argv[1]);"' # Encode strings as URLs (space->%20, etc.) +alias mergepdf='gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=_merged.pdf' # Usage: `mergepdf input{1,2,3}.pdf`` +alias encrypt='gpg -c --no-symkey-cache --cipher-algo AES256' # Encrypt file with AES256 symetric encryption +alias decrypt='gpg' # For the sake of completeness, include decrypt command to the above, though it's only just gpg alias + +# Terminal window swallowing for blocking programs (devour) +alias xdg-open='devour xdg-open' +alias mpv='devour mpv' +alias nomacs='devour nomacs' +alias pcmanfm='devour pcmanfm' +alias spotify='devour spotify' + +# Regular expressions +alias reg_email='echo "[a-Z0-9._%-]+@[a-Z0-9.-]+\.[a-Z]{2,10}"' +alias reg_mac='echo "([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}"' +alias reg_ipv4='echo "([0-9]{1,3}\.){3}[0-9]{1,3}"' +alias reg_ipv6='echo "\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*"' # Also catches loopbacks (::1), (for valid matching, it needs to be this long...) +alias reg_ip='echo "(`reg_ipv4`|`reg_ipv6`)"' # Match both IPv4 and IPv6 + +# Grep aliases +alias grep_email='grep -E `reg_email`' +alias grep_ip='grep -E `reg_ip`' +alias grep_mac='grep -E `reg_mac`' +alias massgrep='grep -RHIni' + +# Network +alias ip-show='curl https://ifconfig.co' # Get global IP address +alias ips="ifconfig -a | grep -oE \"inet6? (addr:)?s?\`reg_ip\`\" | awk '{ sub(/inet6? (addr:)? ?/, \"\"); print }'" +alias lan-device-scan='nmap -T5 -sP 192.168.0.0-255' +alias lan-vuln-scan='nmap -sT -O --script vuln 192.168.0.0-255' +alias ports='netstat -tulanp' +alias listening-ports='netstat -vtlnp --listening' +alias ssh-list='ss | grep ssh' # List all SSH connections +alias serve='python -m http.server' # Serve current directorty as HTTP +alias reverse-dns='host' # It might be easier to just use `host` though +alias torify='source torsocks on' # Pass every command via torsocks +alias untorify='source torsocks off' # Stop passing commands via torsocks + +# Firewall aliases (IPTables/UFW) +alias ipt='iptables' # Shortcut +alias iptlist='iptables -L -n -v --line-numbers' # All rules +alias iptlistin='iptables -L INPUT -n -v --line-numbers' # IN rules +alias iptlistout='iptables -L OUTPUT -n -v --line-numbers' # OUT rules +alias iptlistfw='iptables -L FORWARD -n -v --line-numbers' # FORWARD rules +alias ufw-log='journalctl -f -n 100 -g ufw' # Show UFW log entries in system journal + +# Kernel actions +alias kernel-recompile='cd /usr/src/linux && make -j7 && make -j7 modules_install && make install' +alias kernel-oldconfig='cd /usr/src/linux && make oldconfig' +alias kernel-configure='cd /usr/src/linux && make menuconfig' + +# System actions +alias sv='systemctl' +alias pacnew="find / -name '*.pacnew' 2>/dev/null" # Search for all new configurations after pacman update +alias backup="rsync -avHAXS --delete --filter='dir-merge /.rsync-filter'" # Make full rsync backup, respecting .rsync-filter files for exclusions +alias upload='curl -F "f:1=<-" ix.io' +alias upload-journal='sudo journalctl -b -1 | upload' # Upload journalctl from last boot to ix.io +alias auth-log='journalctl SYSLOG_FACILITY=10 -r' +alias cpu-stress='for i in $(seq $(getconf _NPROCESSORS_ONLN)); do yes > /dev/null & done' # Run `yes > /dev/null` on all cores as stress test +alias nvidia='__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia' # Run app with nvidia (on hybrid mode with optimus) +alias swapout='sudo swapoff -a; sudo swapon -a' # Reset swap (move everything to RAM) +alias mount-ram='mount -t tmpfs tmpfs' # Mount RAM disk for fast filesystem +alias screenlock='xset s activate' # Use DPMS to trigger xss-lock and handle screen locking + +# System info +alias meminfo='free -m -l -t' +alias cpuinfo='lscpu' +alias batinfo='sudo watch -d -n 2 tlp-stat -b' +alias battery='cat /sys/class/power_supply/BAT0/capacity' +alias gpumeminfo='frep -i --color memory /var/log/Xorg.0.log' +alias journalerr='sudo journalctl -p 3 -xb' +alias distro='cat /etc/*-release' +alias diskspace_report="df -P -kHl" +alias kernel='uname -r' + +# System processes +alias psmem='ps auxf | sort -nr -k 4' # Top memory eaters +alias psmem10='psmem | head -10' # Top 10 memory eaters +alias pscpu='ps auxf | sort -nr -k 3' # Top cpu eaters +alias pscpu10='pscpu | head -10' # Top 10 cpu eaters +alias psg='ps aux | grep -v grep | grep -i -e VSZ -e' # Get searchable process with nice output + +# Time info +alias now='date +"%T"' +alias nowtime='now' +alias nowdate='date +"%d-%m-%Y"' +alias week='date +%V' + +# Cleanup +alias clean-trash='rm -rf ~/.local/share/Trash/* || echo "Trash already empty"' +alias clean-downloads='rm -rf ~/Downloads/* || echo "Downloads directory is already empty"' +alias clean-journal='journalctl --vacuum-size=200M || echo "You have to be root to clean journal"' +alias clean-pacman='pacman -Sc || echo "You have to be root to clean pacman cache"' +alias cleanup='clean-trash && clean-down && clean-journal && clean-pacman' + +# Git aliases +alias g='git' +alias gp='git push' +alias gpl='git pull' +alias gf='git fetch' +alias gs='git status --short --branch' +alias gss='git status' +alias ga='git add' +alias gap='git add --patch' +alias gc='git commit' +alias gcm='git commit --message' +alias gb='git branch' +alias gch='git checkout' +alias gchb='git checkout -b' +alias gd='git diff' +alias gdc='git diff --cached' +alias gundo='git reset --soft HEAD~' +alias gredo="git reset 'HEAD@{1}'" + +# Youtube-dl aliases +alias ytv-best='youtube-dl -f bestvideo+bestaudio' +alias yta-best='youtube-dl --extract-audio --audio-format best' +alias yta-mp3='youtube-dl --extract-audio --audio-format mp3' +alias yta-wav='youtube-dl --extract-audio --audio-format wav' + +# Terminal vim-like exits, in case I think the terminal is vim +alias :q='exit' +alias :q!='exit' +alias :wq='exit' +alias :wq!='exit' + +# Shell aliases +alias reload="exec \$SHELL" # Reload the shell (i.e. invoke as a login shell) +alias path='echo -e ${PATH//:/\\n}' # Print each PATH entry on a separate line +alias unsudo='sudo -k' # Reset sudo timeout (sudo will require password) +alias vimwiki='vim -c VimwikiIndex' # Open vimwiki index +alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' +alias tty-clock='tty-clock -Ssc' # Terminal clock screensaver +alias rick='curl -s -L https://raw.githubusercontent.com/ItsDrike/rickrollrc/master/roll.sh| bash' # Terminal rickroll +alias hist='fc -lt "$HISTTIMEFORMAT" 1' +alias sudovim='sudoedit' + +# If user is not root, pass all commands via sudo/doas +if [ "$(id -u)" -ne 0 ]; then + # Enable aliases to be sudoed/doased + # with doas having precedence over sudo if found + + ## Uncomment if you are using autocompletion (is ZSH) + #command -v /usr/bin/sudo > /dev/null && alias doas='nocorrect sudo ' && alias sudo='nocorrect sudo ' + #command -v /usr/bin/doas > /dev/null && alias doas='nocorrect doas ' && alias sudo='nocorrect doas ' + + ## if the above is uncommented, comment this + command -v /usr/bin/sudo > /dev/null && alias doas='sudo ' && alias sudo='sudo ' + command -v /usr/bin/doas > /dev/null && alias doas='doas ' && alias sudo='doas ' +fi + +# enable color support +if [ -x /usr/bin/dircolors ]; then + (test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)") || eval "$(dircolors -b)" + alias dir='dir --color=auto' + alias vdir='vdir --color=auto' + + alias grep='grep --color=auto' + alias cgrep='grep --color=always' + alias fgrep='fgrep --color=auto' + alias egrep='egrep --color=auto' + + alias diff='diff --color=auto' + alias ip='ip --color=auto' + + # Take advantage of $LS_COLORS for completion as well + zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" +fi + +# Normalize `open` across Linux, macOS, and Windows. +# This is needed to make `open` function (see below) cross-platform +if [ ! "$(uname -s)" = 'Darwin' ]; then + if grep -q Microsoft /proc/version; then + # Ubuntu on Windows using the Linux subsystem + alias open='explorer.exe' + else + alias open='xdg-open' + fi +fi + +# Autogenerate python aliases +if [ -f ~/.config/shell/py-alias ]; then + # shellcheck source=/home/itsdrike/.config/shell/py-alias + . "$HOME/.config/shell/py-alias" +fi + +# Functions +if [ -f ~/.config/shell/functions ]; then + # shellcheck source=/home/itsdrike/.config/shell/functions + . "$HOME/.config/shell/functions" +fi + +# Extra +if [ -f ~/.config/shell/extra ]; then + # shellcheck source=/home/itsdrike/.config/shell/extra + . "$HOME/.config/shell/extra" +fi diff --git a/home/.config/shell/environment b/home/.config/shell/environment new file mode 100755 index 0000000..b1692cf --- /dev/null +++ b/home/.config/shell/environment @@ -0,0 +1,78 @@ +#!/bin/sh + +# Environmental variable definitions. +# This file is only sourced once after login, unlike .zshrc/.bashrc +# +# NOTE: This file shouldn't be defined for root account. Sudo +# will not source it (and neither will it source .zshrc/.zprofile), +# which means the XDG definitions will be ignored anyway, and +# defining them may break programs when root is actually logged in. + +# Define some variables for POSIX compatibility +uid="$(id -u)" + +# Default programs +export EDITOR="nvim" +export BROWSER="firefox" +export TERMINAL="alacritty" +export DIFFPROG="nvim -d" +export FILEMANAGER="pcmanfm" + +# XDG Standard paths +export XDG_CONFIG_HOME="$HOME/.config" +export XDG_CACHE_HOME="$HOME/.cache" +export XDG_DATA_HOME="$HOME/.local/share" +export XDG_RUNTIME_DIR="/run/user/$uid" + +# Per-Application XDG settings +export ZDOTDIR="$XDG_CONFIG_HOME/zsh" +export XINITRC="$XDG_CONFIG_HOME/x11/xinitrc" +#export XAUTHORITY="$XDG_RUNTIME_DIR/Xauthority" # This line will break some DMs. +export LESSHISTFILE="-" +export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc" +export WGETRC="$XDG_CONFIG_HOME/wget/wgetrc" +export GNUPGHOME="$XDG_DATA_HOME/gnupg" +export GOPATH="$XDG_DATA_HOME/go" +export CARGO_HOME="$XDG_DATA_HOME/cargo" +export RUSTUP_HOME="$XDG_DATA_HOME/rustup" +export GRADLE_USER_HOME="$XDG_DATA_HOME/gradle" +export _JAVA_OPTIONS="-Djava.util.prefs.userRoot=$XDG_CONFIG_HOME/java" +export NPM_CONFIG_USERCONFIG="$XDG_CONFIG_HOME/npm/npmrc" +export NUGET_PACKAGES="$XDG_CACHE_HOME/NuGetPackages" +# Less commonly used applications +export _ZL_DATA="$XDG_DATA_HOME/zlua" +export SQLITE_HISTORY="$XDG_DATA_HOME/sqlite_history" +export WAKATIME_HOME="$XDG_CONFIG_HOME/wakatime" +export IPYTHONDIR="$XDG_CONFIG_HOME/ipython" +export PYENV_ROOT="$XDG_DATA_HOME/pyenv" +export MYPY_CACHE_DIR="$XDG_CACHE_HOME/mypy" +#export PYLINTHOME="$XDG_CACHE_HOME/pylint" +#export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker" +#export CUDA_CACHE_PATH="$XDG_CACHE_HOME/nv" + +# Colorful man pages +# If bat is installed, use it as manpager +# shellcheck disable=SC2155 +if command -v bat > /dev/null; then + export MANPAGER="sh -c 'col -bx | bat -l man -p'" +else + export LESS_TERMCAP_mb="$(printf '%b' '[1;31m')" + export LESS_TERMCAP_md="$(printf '%b' '[1;36m')" + export LESS_TERMCAP_me="$(printf '%b' '[0m')" + export LESS_TERMCAP_so="$(printf '%b' '[01;44;33m')" + export LESS_TERMCAP_se="$(printf '%b' '[0m')" + export LESS_TERMCAP_us="$(printf '%b' '[1;32m')" + export LESS_TERMCAP_ue="$(printf '%b' '[0m')" +fi + +# Other program settings +export HISTTIMEFORMAT="%Y-%m-%d %T " +export SUDO_ASKPASS="$HOME/.local/bin/scripts/dmenu/dmenupass" +export PIPENV_VENV_IN_PROJECT=1 # Force pipenv to create new environments within projects ./.venv +export XSECURELOCK_SHOW_HOSTNAME=0 # Don't show hostname in xsecurelock +export XSECURELOCK_SHOW_DATETIME=1 # Show current date and time in xsecurelock +export QT_QPA_PLATFORMTHEME="qt5ct" # Have QT use theme from qt5ct. +#export QT_STYLE_OVERRIDE="gtk2" # Have QT use the gtk2 theme (needs aur/qt5-styleplugins) + +# Remove irrelevant variables added for posix compatibility +unset posix diff --git a/home/.config/shell/extra b/home/.config/shell/extra new file mode 100755 index 0000000..9f3ffc8 --- /dev/null +++ b/home/.config/shell/extra @@ -0,0 +1,245 @@ +#!/usr/bin/env zsh + +# ---------------------------------------------------------------- +# Additional aliases +alias cfextra='vim ~/.config/shell/extra' +alias cflvim='lvim ~/.config/lvim/config.lua' +alias cfgit='vim ~/.config/git/config' +alias cfhypr="vim ~/.config/hypr/hyprland.conf" +alias cfwaybar='vim ~/.config/waybar/config-hypr' +alias dotsync='git checkout arch && git push && git checkout gentoo && git merge --ff arch && git push && git checkout arch' +alias kbsk='setxkbmap sk qwerty' +alias kbus='setxkbmap us' +alias update-webpage='ssh webpage "cd /var/www/itsdrike.com; git pull; ./scripts/build.sh"' +alias octave='octave --quiet' +alias savekern='cp /proc/vmcore /root/crash.dump' +alias discord-bump='sleep $((2*60*60)) && notify-send "Bump" "Bump time expired"' +alias svim='nvim' +alias vim='lvim' +alias vpn-home='sudo systemctl stop wg-quick@wgivpn && sudo systemctl start wg-quick@wg0' +alias vpn-ivpn='sudo systemctl stop wg-quick@wg0 && sudo systemctl start wg-quick@wgivpn' +alias vpn-wg0='vpn-home' +alias vpn-wgivpn='vpn-ivpn' +alias vpn-off='sudo systemctl stop wg-quick@wg0 && sudo systemctl stop wg-quick@wgivpn' +alias spotify-adblock='env LD_PRELOAD=/usr/lib/spotify-adblock.so spotify' +alias mono-on='pacmd load-module module-remap-sink sink_name=mono master=2 channels=1' +alias mono-off='pacmd unload-module module-remap-sink' + +# ---------------------------------------------------------------- +# Additional functions + +git-uni() { + git config --local commit.gpgsign false + git config --local user.email "p_vacho@utb.cz" + git config --local user.name "Peter Vacho" +} + +dot-sync() { + target="$(realpath -s "$1")" + if [[ "$target" == "$HOME/"* ]]; then + rel_path="$(realpath --relative-to="$HOME" "$target")" + dot_target="$dothome/$rel_path" + else + rel_path="$(realpath --relative-to="/" "$target")" + dot_target="$dotroot/$rel_path" + fi + + >&2 echo "Would copy $target -> $dot_target" + if [[ -d "$target" ]]; then + rsync -av --delete "${@:2}" "$target/" "$dot_target" + else + rsync -av "${@:2}" "$target" "$dot_target" + fi +} + +pytemp() { + dir="$(mktemp --tmpdir=/tmp -d "tmp.pytemp.XXXXXX")" + pushd "$dir" >/dev/null + yes "" | poetry init + cp ~/Personal/Programming/Python/Templates/GitHub/.flake8 . + sed -i 's/project_name/src/' ./.flake8 + poetry add --dev flake8 black isort pyright # also performs install + mkdir ./src + touch ./src/__init__.py + echo "def main():\n ...\n\n" > ./src/__main__.py + echo "if __name__ == \"__main__\":\n main()" >> ./src/__main__.py + poetry run lvim +2 -c 'execute "normal $ciw" | startinsert!' ./src/__main__.py + popd + rm -rf "$dir" +} + + +setuppy(){ + cp -r "/home/itsdrike/Personal/Programming/Python/Templates/GitHub" "$1" + cd "$1" + git init + poetry update + poetry install + echo "TODO" >> .gitignore_local + poetry shell + # Show all places where we used "project_name", these are expected to be renamed + grep -RHIni --exclude-dir=.venv project_name +} + +webpage-put(){ + scp $@ webpage:/var/www/itsdrike.com/etc +} + +webpage-remove(){ + sftp webpage:/var/www/itsdrike.com/etc <<< "rm $@" +} + +vidtrim(){ + if [ $# -ne 3 ]; then + echo "Invalid number of parameters passed!" + echo "Usage: vidtrim [file name] [start time] [end time]" + return 1 + fi + no_ext_name=$1:r + ext=$1:e + i=1 + while true; do + new_name="${no_ext_name}-trimmed-${i}.${ext}" + if [ -e "$new_name" ]; then + i=$((i + 1)) + else + break + fi + done + + ffmpeg -ss "$2" -i "$1" -to "$3" -c copy -copyts "$new_name" +} + +vidmerge(){ + if [ $# -lt 3 ]; then + echo "Invalid number of parameters passed!" + echo "Usage: vidmerge [input path 1] [input path 2] [optionally more inputs ...] [output name]" + echo "Example: vidmerge . REC-2020-05-.*.mp4 output.mp4" + return 1 + fi + + # Parse the input + first_file="$1" + files="$2" + out="$3" + shift; shift; shift + # Process extra filenames, in case there's more than 2 to merge + while [ $# -gt 0 ]; do + files="$files\n$out" + out="$1" + shift + done + + # Prefer MP4Box over ffmpeg if installed + # this is benefitial because merging with ffmpeg results in files with + # messed up timeline (the file will be a merge product of all given files, + # but the timeline will suddenly skip i.e. from 10s to 50s seemlessly, resulting + # in proper merge, but with weird timeline info) + if ! command -v MP4Box >/dev/null 2>&1; then + files="$first_file\n$files" + # Create file with all of the file paths to concat for ffmpeg + substring="'" + if test "${files#*$substring}" != "$files"; then + echo "Can't handle files with $substring in their names!" + return 1 + fi + loc="files.txt" + echo "$files" | while IFS= read -r line; do + printf "file '%s'\n" "$line" >> "$loc" + done + + + if ffmpeg -f concat -safe 0 -i "$loc" -c copy "$out"; then + rm "$loc" + else + echo "Ffmpeg failed, check '$loc' file, containing the files passed to ffmpeg" + fi + else + cat_list="$(echo "$files" | xargs -d '\n' printf -- '-cat "%s" ')" + cmd="MP4Box -add \"$first_file\" $cat_list \"$out\"" + echo "$cmd" + if eval "$cmd"; then + echo "Video merge complete, generated output: $out" + else + echo "MP4Box failed, used cmd: $cmd" + fi + fi +} + +vidrot(){ + if [ $# -ne 2 ]; then + echo "Invalid number of parameters passed!" + echo "Usage: vidrot [video file] [rotation (0/1/2/3)]" + echo "0: cclock_flip (90° counterclockwise and vertical flip)" + echo "1: clock (90° clockwise)" + echo "2: cclock (90° counterclockwise)" + echo "3: clock_flip (90° clockwise and vertical flip)" + return 1 + fi + name="$1" + rotation="$2" + no_ext_name=$name:r + ext=$name:e + editname="${no_ext_name}-rot.${ext}" + ffmpeg -i "$name" -vf "transpose=$rotation" "$editname" +} + +# ---------------------------------------------------------------- +# Additional exports +export dothome="$HOME/Personal/dotfiles/home" +export dotroot="$HOME/Personal/dotfiles/root" +export dotvim="$dothome/.config/nvim" + + +# ---------------------------------------------------------------- +# Pacman/Emerge +if command -v pacman > /dev/null; then + alias pkg-info='pacman -Si' # Info about a package in sync index + alias pkg-info-local='pacman -Qi' # Same as above, but for locally installed pkgs + alias pkg-file-owner='pacman -F' # Show package that owns given file in sync index + alias pkg-file-owner-regex='pacman -Fx' # Same as above, but works with partial names/regex + alias pkg-file-owner-local='pacman -Qo' # Same as above, but for locally installed pkgs + alias pkg-owned-files='pacman -Fl' # Show all files owned by given package in sync index + alias pkg-owned-files-local='pacman -Ql' # Same as above 2, but for locally installed pkgs + alias pkg-group-list='pacman -Sg' # List all pkgs that will be installed with a group + alias pkg-group-list-local='pacman -Qg' # Same as above, but from locally installed pkgs + alias pkg-orphans='pacman -Qtdq' + + alias pkg-get-upgrades='pacman -Syyuw' # Download new pkgs, but don't upgrade them + alias pkg-extract='pacman -Syw --cachedir .' # Download given pkg to current directory + alias pkg-clean-cache='pacman -Sc' # Remove old packages in pacman cache + + alias pkg-vuln-upgrade="pacman -Sy \"\$(arch-audit --upgradable --quiet | awk '{sub(/>=.+/, \"\"); print}' | paste -s -d ' ')\"" # Upgrade all vulnerable packages, with released fixes + alias vuln='arch-audit' # Show vulnerable packages that can be upgraded (Arch Linux) + + # Get fastest mirrors (using reflector) + alias mirror="sudo reflector -f 30 -l 30 --number 10 --verbose --save /etc/pacman.d/mirrorlist" + alias mirrord="sudo reflector --latest 50 --number 20 --sort delay --save /etc/pacman.d/mirrorlist" + alias mirrors="sudo reflector --latest 50 --number 20 --sort score --save /etc/pacman.d/mirrorlist" + alias mirrora="sudo reflector --latest 50 --number 20 --sort age --save /etc/pacman.d/mirrorlist" +fi + +if command -v emerge > /dev/null; then + if command -v eix > /dev/null; then + alias pkg-sync='eix-sync' + alias pkg-search='eix' + else + alias pkg-sync='emerge --sync --quiet=n' + alias pkg-search='emerge -s' + fi + alias pkg-update='emerge --update --deep @world' + alias pkg-upgrade='pkg-sync && pkg-update' + alias pkg-changed-use='pkg-update --changed-use' + alias pkg-recompile-all='emerge -e @world' + + alias pkg-which='equery which' + alias pkg-size='equery size' + alias pkg-depgraph='equery depgraph' + alias pkg-depends='equery depends' + alias pkg-check='equery check' + alias pkg-uses='equery uses' + alias pkg-keywords='equery keywords' + + alias update-conf='dispatch-conf' +fi + diff --git a/home/.config/shell/functions b/home/.config/shell/functions new file mode 100755 index 0000000..81c8b26 --- /dev/null +++ b/home/.config/shell/functions @@ -0,0 +1,291 @@ +#!/bin/sh +# TODO: Currently, this file isn't entirely POSIX compatible, +# it will run fine with bash or zsh, however some functions may cause +# issues with pure POSIX. The fill will however run fine, the errors +# would only occur if the incompatible functions would be started. + +# Show application listening on given port +port() { + sudo netstat -pln | grep "$1" | awk '{print $NF}' +} + +# Create a new directory and enter it +mkd() { + # shellcheck disable=SC2164 + mkdir -p "$1" && cd "$1"; +} + +# `o` with no arguments opens the current directory, otherwise opens the given +# location +o() { + if [ $# -eq 0 ]; then + open .; + else + open "$@"; + fi; +} + +# Use bat for nicer git diffs +batdiff() { + git diff --name-only --diff-filter=d | xargs bat --diff +} + +# Determine size of a file or total size of a directory +dirsize() { + if du -b /dev/null > /dev/null 2>&1; then + arg=-sbh; + else + arg=-sh; + fi + if [[ -n "$*" ]]; then + \du $arg -- "$@"; + else + \du $arg .[^.]* ./*; + fi; +} + +randmac() { + sudo ip link set dev "$1" down + sudo macchanger -A "$1" + sudo ip link set dev "$1" up +} + +# Go to the root of a git tree +cdgit () { + if [ "$(git rev-parse --is-inside-work-tree > /dev/null 2>&1)" -eq 0 ]; then + while ! [ -d .git ]; do + cd .. + done + return 0 + else + echo "Not a git directory" + return 1 + fi +} + +# Create a data URL from a file +dataurl() { + mimeType="$(file -b --mime-type "$1")" + if echo "$mimeType" | grep -e "^text/.*$" >/dev/null; then + mimeType="${mimeType};charset=utf-8" + fi + echo "data:${mimeType};base64,$(openssl base64 -in "$1" | tr -d '\n')"; +} + +# `tre` is a shorthand for `tree` with hidden files and color enabled, ignoring +# the `.git` directory, listing directories first. The output gets piped into +# `less` with options to preserve color and line numbers, unless the output is +# small enough for one screen. +tre() { + tree -I '.git|node_modules|bower_components' --group-directories-first "$@" | less -FRNX; +} + + + +# Show all the names (CNs and SANs) listed in the SSL certificate +# for a given domain +getcertnames() { + if [ -z "${1}" ]; then + echo "ERROR: No domain specified."; + return 1; + fi; + + domain="${1}"; + echo "Testing ${domain}…"; + echo ""; # newline + + tmp=$(echo -e "GET / HTTP/1.0\nEOT" \ + | openssl s_client -connect "${domain}:443" -servername "${domain}" 2>&1); + + if [[ "${tmp}" = *"-----BEGIN CERTIFICATE-----"* ]]; then + certText=$(echo "${tmp}" \ + | openssl x509 -text -certopt "no_aux, no_header, no_issuer, no_pubkey, \ + no_serial, no_sigdump, no_signame, no_validity, no_version"); + echo "Common Name:"; + echo ""; # newline + echo "${certText}" | grep "Subject:" | sed -e "s/^.*CN=//" | sed -e "s/\/emailAddress=.*//"; + echo ""; # newline + echo "Subject Alternative Name(s):"; + echo ""; # newline + echo "${certText}" | grep -A 1 "Subject Alternative Name:" \ + | sed -e "2s/DNS://g" -e "s/ //g" | tr "," "\n" | tail -n +2; + return 0; + else + echo "ERROR: Certificate not found."; + return 1; + fi; +} + +# Compare original and gzipped file size +gz_compare() { + origsize=$(wc -c < "$1"); + gzipsize=$(gzip -c "$1" | wc -c); + ratio=$(echo "$gzipsize * 100 / $origsize" | bc -l); + printf "orig: %d bytes\n" "$origsize"; + printf "gzip: %d bytes (%2.2f%%)\n" "$gzipsize" "$ratio"; +} + +# Extract almost any archive +extract() { + if [ -z "$1" ]; then + # display usage if no parameters given + echo "Usage: extract ." + echo " extract [path/file_name_2.ext] [path/file_name_3.ext]" + return 1 + else + for n in "$@" + do + if [ -f "$n" ] ; then + case "${n%,}" in + *.tar.bz2|*.tar.gz|*.tar.xz|*.tbz2|*.tgz|*.txz|*.tar) + tar xvf "$n" ;; + *.lzma) unlzma ./"$n" ;; + *.bz2) bunzip2 ./"$n" ;; + *.rar) unrar x -ad ./"$n" ;; + *.gz) gunzip ./"$n" ;; + *.zip) unzip ./"$n" ;; + *.z) uncompress ./"$n" ;; + *.7z|*.arj|*.cab|*.chm|*.deb|*.dmg|*.iso|*.lzh|*.msi|*.rpm|*.udf|*.wim|*.xar) + 7z x ./"$n" ;; + *.xz) unxz ./"$n" ;; + *.exe) cabextract ./"$n" ;; + *) + echo "extract: '$n' - unknown archive method" + return 1 + ;; + esac + else + echo "'$n' - file does not exist" + return 1 + fi + done +fi +} + +# Create a .tar.gz archive, using `zopfli`, `pigz` or `gzip` for compression +targz() { + # Combine given names spearated with spaces as the filename + tmpFile="${*%/}.tar" + + tar -cvf "${tmpFile}" "${@}" || return 1 + + size=$( + stat -f"%z" "${tmpFile}" 2> /dev/null; # macOS `stat` + stat -c"%s" "${tmpFile}" 2> /dev/null; # GNU `stat` + ); + + cmd=""; + if (( size < 52428800 )) && hash zopfli 2> /dev/null; then + # the .tar file is smaller than 50 MB and Zopfli is available; use it + cmd="zopfli"; + else + if hash pigz 2> /dev/null; then + cmd="pigz"; + else + cmd="gzip"; + fi; + fi; + + echo "Compressing .tar ($((size / 1000)) kB) using \`${cmd}\`…"; + "${cmd}" -v "${tmpFile}" || return 1; + [ -f "${tmpFile}" ] && rm "${tmpFile}"; + + zippedSize=$( + stat -f"%z" "${tmpFile}.gz" 2> /dev/null; # macOS `stat` + stat -c"%s" "${tmpFile}.gz" 2> /dev/null; # GNU `stat` + ); + + echo "${tmpFile}.gz ($((zippedSize / 1000)) kB) created successfully."; +} + +anonymize() { + # Reset the prompt on initial run to allow this script + # to be ran multiple times without user having to reload + # PS1 manually + # shellcheck source=/home/itsdrike/.config/shell/prompt + . "${XDG_CONFIG_DIR:-$HOME/.config}/shell/prompt" + + # Regular expression to match 0-255 numbers (color) + color_int_re='^(0+)?([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' + + # Defaults + NAME="%n" + MACHINE="" + #NAME_COLOR="%F{047}" + NAME_COLOR="%F{172}" + #DIR_COLOR="%F{027}" + DIR_COLOR="%F{158}" + AT_COLOR="%F{004}" + MACHINE_COLOR="%F{070}" + + while [ $# -gt 0 ]; do + key=$1 + + case $key in + -n|--name) + NAME=$2 + shift + shift + ;; + -m|--machine) + MACHINE=$2 + shift + shift + ;; + -nc|--name-color) + if [[ $2 =~ $color_int_re ]]; then + NAME_COLOR="%F{$2}" + else + NAME_COLOR=$2 + fi + shift + shift + ;; + -dc|--dir-color) + if [[ $2 =~ $color_int_re ]]; then + DIR_COLOR="%F{$2}" + else + DIR_COLOR=$2 + fi + shift + shift + ;; + -mc|--machine-color) + if [[ $2 =~ $color_int_re ]]; then + MACHINE_COLOR="%F{$2}" + else + MACHINE_COLOR=$2 + fi + shift + shift + ;; + -ac|--at-color) + if [[ $2 =~ $color_int_re ]]; then + AT_COLOR="%F{$2}" + else + AT_COLOR=$2 + fi + shift + shift + ;; + *) + echo "Unrecognized argument: $key" + echo "Arguments: -n|--name, -m|--machine, -nc|--name-color, -dc|--dir-color, -mc|--machine-color, -ac|--at-color" + return 1 + ;; + esac + done + + + OLD_LINE="%F{047}%n%f %F{027}" + + [ -n "$NAME" ] && NEW_LINE="${NAME_COLOR}${NAME}" + [ -n "$NAME" ] && [ -n "$MACHINE" ] && NEW_LINE="${NEW_LINE}${AT_COLOR}@" + [ -n "$MACHINE" ] && NEW_LINE="${NEW_LINE}${MACHINE_COLOR}${MACHINE}" + [ -n "$NAME" ] || [ -n "$MACHINE" ] && NEW_LINE="${NEW_LINE}%f " + NEW_LINE="${NEW_LINE}${DIR_COLOR}" + + # Use new anonymized name, machine and colors in PS1 + PS1=${PS1/"$OLD_LINE"/"$NEW_LINE"} +} + diff --git a/home/.config/shell/handlers b/home/.config/shell/handlers new file mode 100755 index 0000000..5434015 --- /dev/null +++ b/home/.config/shell/handlers @@ -0,0 +1,40 @@ +#!/bin/sh + +if command -v pkgfile > /dev/null; then + # Command not found hook that uses `pkgfile` package + # to search through the package index in order to find + # a package which includes given command, which was resolved + # and not found, if there are no such packages, only print + # command not found message + command_not_found_handler() { + cmd="$1" + printf 'zsh: command not found: %s' "$cmd" # print command not found asap, then search for packages + repos="$(pkgfile "$cmd")" + if [ -n "$repos" ]; then + printf '\r%s may be found in the following packages:\n' "$cmd" + echo "$repos" | while read -r pkg; do + printf ' %s\n' "$pkg" + done + else + printf '\n' + fi + return 127 + } +elif [ -x /usr/lib/command-not-found ] || [ -x /usr/share/command-not-found/command-not-found ]; then + # Ubuntu handle for bash default command-not-found + # it works similarely to the above arch alternative, + # this is based on the original bash implementation + command_not_found_handler() { + # check because cmd not found could've been removed in the meantime + if [ -x /usr/lib/command-not-found ]; then + /usr/lib/command-not-found -- "$1" + return $? + elif [ -x /usr/share/command-not-found/command-not-found ]; then + /usr/share/command-not-found/command-not-found -- "$1" + return $? + else + printf "%s: command not found\n" "$1" >&2 + return 127 + fi + } +fi diff --git a/home/.config/shell/keybinds b/home/.config/shell/keybinds new file mode 100755 index 0000000..f95b1cc --- /dev/null +++ b/home/.config/shell/keybinds @@ -0,0 +1,65 @@ +#!/usr/bin/env zsh +# shellcheck disable=SC2030,SC2031,SC2015 +# Set default keybindings (mostly from oh-my-zsh) + +# Make sure that the terminal is in application mode when zle is active, since +# only then values from $terminfo are valid +if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then + function zle-line-init() { + echoti smkx + } + function zle-line-finish() { + echoti rmkx + } + zle -N zle-line-init + zle -N zle-line-finish +fi + +# Use emacs keybindings +bindkey -e + +# Start typing + [Up-Arrow] - fuzzy find history forward +if [ -n "${terminfo[kcuu1]}" ]; then + autoload -U up-line-or-beginning-search + zle -N up-line-or-beginning-search + bindkey "${terminfo[kcuu1]}" up-line-or-beginning-search +fi +# Start typing + [Down-Arrow] - fuzzy find history backward +if [ -n "${terminfo[kcud1]}" ]; then + autoload -U down-line-or-beginning-search + zle -N down-line-or-beginning-search + bindkey "${terminfo[kcud1]}" down-line-or-beginning-search +fi + +# [Home] - Go to beginning of line +[ -n "${terminfo[khome]}" ] && bindkey "${terminfo[khome]}" beginning-of-line || bindkey "^[[H" beginning-of-line +# [End] - Go to end of line +[ -n "${terminfo[kend]}" ] && bindkey "${terminfo[kend]}" end-of-line || bindkey "^[[F" end-of-line + +# [Shift-Tab] - move through the completion menu backwards +[ -n "${terminfo[kcbt]}" ] && bindkey "${terminfo[kcbt]}" reverse-menu-complete + +# [Backspace] - delete backward +bindkey '^?' backward-delete-char +# [Delete] - delete forward +[ -n "${terminfo[kdch1]}" ] && bindkey "${terminfo[kdch1]}" delete-char || bindkey "^[[3~" delete-char +# [Ctrl-Delete] - delete whole forward-word +bindkey '^[[3;5~' kill-word + +# [Ctrl-RightArrow] - move forward one word +bindkey '^[[1;5C' forward-word +# [Ctrl-LeftArrow] - move backward one word +bindkey '^[[1;5D' backward-word + +# [Ctrl-r] - Search backward incrementally for a specified string. The string may begin with ^ to anchor the search to the beginning of the line. +bindkey '^r' history-incremental-search-backward +# [PageUp] - Up a line of history +[ -n "${terminfo[kpp]}" ] && bindkey "${terminfo[kpp]}" up-line-or-history +# [PageDown] - Down a line of history +[ -n "${terminfo[knp]}" ] && bindkey "${terminfo[knp]}" down-line-or-history + +# [Space] - do history expansion on space +bindkey ' ' magic-space + +# [ctrl+space] Accept suggestion from zsh-autosuggestions plugin +bindkey '^ ' autosuggest-accept diff --git a/home/.config/shell/profile b/home/.config/shell/profile new file mode 100755 index 0000000..b48552c --- /dev/null +++ b/home/.config/shell/profile @@ -0,0 +1,19 @@ +#!/bin/sh + +# User .profile definition. +# This file is only sourced once, after login, Unlike +# .zshrc/.bashrc, which will run whenever a new terminal +# is opened. + +# Add all folders in ~/.local/bin into PATH +# Some window managers require this line to be in profile +# not in .zshenv +PATH+=":${$(find ~/.local/bin -type d | tr '\n' ':')%%:}" + +# Start graphical session automatically on tty1 if startx is aviable +if [ "$(tty)" = "/dev/tty1" ] && [ "$UID" != 0 ]; then + if command -v Hyprland >/dev/null; then + ! pidof -s Hyprland >/dev/null 2>&1 && launch-hypr + fi +fi + diff --git a/home/.config/shell/prompt b/home/.config/shell/prompt new file mode 100755 index 0000000..ca0aaa3 --- /dev/null +++ b/home/.config/shell/prompt @@ -0,0 +1,187 @@ +#!/usr/bin/env zsh +# shellcheck disable=SC2155 + +# Configuration variables: + +# Once we are too deep in the filestructure, we can usually afford to shorten +# the whole working directory and only print something like ~/.../dir3/dir4/dir5 +# instead of ~/dir1/dir2/dir3/dir4/dir5. If this isn't desired, set this to 0 +USE_SHORTENED_WORKDIR=1 + +# Show how much time it took to run a command +CMD_TIME_SHOW=1 +# Minimum units to show the time precision, if +# we use "s" (seconds), and the output took 0s, +# we don't print the output at all to avoid clutter. +# Same goes for any other units, however with "ms" +# (miliseconds), this is very unlikely +# Valid options: ms/s/m/h/d +CMD_TIME_PRECISION="s" +# Minimum time in miliseconds, to print the time took, +# if the command takes less than this amount of miliseconds, +# don't bother printing the time took, this is nice if you +# don't need to see how long commands like 'echo' took +# Setting this to 0 will always print the time taken +CMD_TIME_MINIMUM=100 + +# hide EOL sign ('%') +export PROMPT_EOL_MARK="" + +# TTY (pure linux) terminal only has 8-bit color support +# (unless you change it in kernel), respect this and downgrade +# the color scheme accordingly (it won't look best, but it's +# still better than no colors) +if [ "$TERM" = "linux" ]; then + GREEN="%F{002}" + RED="%F{001}" + ORANGE="%F{003}" + BLUE="%F{004}" + LBLUE="%F{006}" + PURPLE="%F{005}" +else + GREEN="%F{047}" + RED="%F{196}" + ORANGE="%F{214}" + BLUE="%F{027}" + LBLUE="%F{075}" + PURPLE="%F{105}" +fi +RESET="%f" + +# Signals git status of CWD repository (if any) +git_prompt() { + ref=$(command git symbolic-ref HEAD 2> /dev/null) || ref=$(command git rev-parse --short HEAD 2> /dev/null) || return 0 + echo -n " $ORANGE${ref#refs/heads/}" + + if [ -n "$(git status --short 2>/dev/null)" ]; then + echo "$RED+" + fi +} + +# Adds @chroot or @ssh +foreign_prompt() { + if [ "$(awk '$5=="/" {print $1}' /dev/null; then + echo ";$full_version;" + else + echo ';;' + fi +} + +# Prints version number extracted from alias for given version +# $1 - version used in the alias (for example '3.6', '3', or even '', but also 'pypy3.6', ...) +get_alias_version() { + alias_version="$1" + definition="$(alias "py$alias_version")" + full_version="$(echo "$definition" | cut -d= -f3 | cut -d' ' -f1)" + + version_info="$(parse_python_version "$full_version")" + version="$(echo "$version_info" | cut -d';' -f2)" + echo "$version" +} + +# Compares 2 python versions in major, minor and micro parts +# $1 - version #1 +# $2 - version #2 +# Returns: +# 0 - version #1 is newer +# 1 - version #2 is newer +# 2 - versions are equal +version_compare() { + version_1="$1" + version_2="$2" + # ZSH Only: + version_1=("${(@s:.:)version_1}") + version_2=("${(@s:.:)version_2}") + major_1=$version_1[1] + major_2=$version_2[1] + minor_1=$version_1[2] + minor_2=$version_2[2] + micro_1=$version_1[3] + micro_2=$version_2[3] + # POSIX, but slow: + # major_1="$(echo "$version_1" | cut -d. -f1)" + # major_2="$(echo "$version_2" | cut -d. -f1)" + # minor_1="$(echo "$version_1" | cut -d. -f2)" + # minor_2="$(echo "$version_2" | cut -d. -f2)" + # micro_1="$(echo "$version_1" | cut -d. -f3)" + # micro_2="$(echo "$version_2" | cut -d. -f3)" + + # Compare majors + if [ $major_1 -gt $major_2 ]; then + # version 1's major is bigger, version 1 is newer + return 0 + elif [ $major_1 -lt $major_2 ]; then + # version 1's major is smaller, version 2 is newer + return 1 + fi + + # Majors equal, compare minors + if [ $minor_1 -gt $minor_2 ]; then + # version 1's minor is bigger, version 1 is newer + return 0 + elif [ $minor_1 -lt $minor_2 ]; then + # version 1's major is smaller, version 2 is newer + return 1 + fi + + # Minors equal, compare micros + if [ $micro_1 -gt $micro_2 ]; then + # version 1's micro is bigger, version 1 is newer + return 0 + elif [ $micro_1 -lt $micro_2 ]; then + # version 1's micro is smaller, version 2 is newer + return 1 + fi + + # Micros equal, versions equal + return 2 +} + +# Define new aliases if they don't already exsist, in which case override +# if the current version is newer than the version in the alias +# $1 - full valid pyenv python version (for example '3.6.12', `3.11-dev`, or `pypy3.6-7.2.0-src`) +# $2 - version used in the alias (for example '3.6', '3', or even '', but also `pypy3.7`, ...) +try_define_aliases() { + version="$1" + alias_version="$2" + + # Check if alias already exists + if alias "py$alias_version" >/dev/null; then + # Compare version from the existing alias with current version, + # if current is newer, override the existing alias(es) + defined_version="$(get_alias_version "$alias_version")" + if version_compare "$version" "$defined_version"; then + define_aliases "$version" "$alias_version" + # echo "Overwrote '$alias_version' aliases to point to '$version'" + return 0 + else + return 1 + fi + fi + + # The aliases aren't already defined, it's safe to create them + define_aliases "$version" "$alias_version" + # echo "Made '$alias_version' aliases pointing to '$version'" + return 0 +} + +define_version_aliases() { + prefix="$1" + version="$2" + suffix="$3" + + + # ZSH only: + version_data=("${(@s:.:)version}") + major_version=$version_data[1] + minor_version=$version_data[2] + # POSIX, but slow: + # major_version="$(echo "$version" | cut -d. -f1)" + # minor_version="$(echo "$version" | cut -d. -f2)" + + # Define the major.minor.micro (full) alias + try_define_aliases "$version" "$prefix$version$suffix" + # Define the major.minor alias + try_define_aliases "$version" "$prefix$major_version.$minor_version$suffix" + # Define the major alias + try_define_aliases "$version" "$prefix$major_version$suffix" + # Define top level alias + try_define_aliases "$version" "$prefix$suffix" +} + +for python_dir in "$PYENV_ROOT"/versions/*/ ; do + full_version="$(basename $python_dir)" + + version_info="$(parse_python_version "$full_version")" + if [ $version_info = ';;' ]; then + # Version info wasn't obtained successfully, skip this version + echo "Skipped $full_version" + continue + fi + + # ZSH only: + version_data=("${(@s:;:)version_info}") + prefix=$version_data[1] + version=$version_data[2] + suffix=$version_data[3] + # POSIX, but slow: + # prefix="$(echo "$version_info" | cut -d';' -f1)" + # version="$(echo "$version_info" | cut -d';' -f2)" + # suffix="$(echo "$version_info" | cut -d';' -f3)" + + # startTime=$(date +%N) + define_version_aliases "$prefix" "$version" "$suffix" + # endTime=$(date +%N) + # nanos="$(expr $endTime - $startTime)" + # echo "took $(expr $nanos / 1000000) miliseconds" +done + +if command -v poetry >/dev/null 2>&1; then + alias poetry-pyenv='poetry env use "$(pyenv which python)" && poetry install' +fi diff --git a/home/.config/swappy/config b/home/.config/swappy/config new file mode 100644 index 0000000..dbfe13c --- /dev/null +++ b/home/.config/swappy/config @@ -0,0 +1,9 @@ +[Default] +save_dir=$HOME/Pictures/Screenshots +save_filename_format=Screenshot_%Y-%M-%D_%H-%M-%S.png +show_panel=false +line_size=5 +text_size=20 +text_font=JetBrains Mono +early_exit=true +paint_mode=rectangle diff --git a/home/.config/swayidle/config b/home/.config/swayidle/config new file mode 100644 index 0000000..958398c --- /dev/null +++ b/home/.config/swayidle/config @@ -0,0 +1,4 @@ +timeout 300 "hyprctl dispatch dpms off" resume "hyprctl dispatch dpms on" +timeout 310 "loginctl lock-session" +before-sleep swaylock -fF +lock swaylock -fF diff --git a/home/.config/swaylock/config b/home/.config/swaylock/config new file mode 100644 index 0000000..1f68e36 --- /dev/null +++ b/home/.config/swaylock/config @@ -0,0 +1,31 @@ +ignore-empty-password +clock + +color=1d1f21 +indicator-idle-visible +indicator-radius=150 +indicator-thickness=30 + +inside-color=1d1f21 +inside-clear-color=1d1f21 +inside-ver-color=1d1f21 +inside-wrong-color=1d1f21 + +key-hl-color=7aa6daaa +bs-hl-color=d54e53aa + +separator-color=55555555 + +line-color=1d1f21 +line-uses-ring + +text-color=81a2be +text-clear-color=b5bd68 +text-caps-lock-color=f0c674 +text-ver-color=81a2be +text-wrong-color=cc6666 + +ring-color=81a2be55 +ring-ver-color=81a2be +ring-clear-color=b5bd6811 +ring-wrong-color=cc6666 diff --git a/home/.config/user-dirs.dirs b/home/.config/user-dirs.dirs new file mode 100644 index 0000000..52196bb --- /dev/null +++ b/home/.config/user-dirs.dirs @@ -0,0 +1,17 @@ +# This file is written by xdg-user-dirs-update +# If you want to change or add directories, just edit the line you're +# interested in. All local changes will be retained on the next run. +# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped +# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an +# absolute path. No other format is supported. +# +#XDG_DESKTOP_DIR="$HOME/Desktop" +XDG_DOWNLOAD_DIR="$HOME/Downloads" +#XDG_TEMPLATES_DIR="$HOME/Templates" +#XDG_PUBLICSHARE_DIR="$HOME/Public" +#XDG_DOCUMENTS_DIR="$HOME/Documents" +XDG_DOCUMENTS_DIR="$HOME/Personal" +#XDG_MUSIC_DIR="$HOME/Music" +XDG_MUSIC_DIR="$HOME/Audio" +XDG_PICTURES_DIR="$HOME/Pictures" +#XDG_VIDEOS_DIR="$HOME/Videos" diff --git a/home/.config/user-dirs.locale b/home/.config/user-dirs.locale new file mode 100644 index 0000000..3e0b419 --- /dev/null +++ b/home/.config/user-dirs.locale @@ -0,0 +1 @@ +en_US \ No newline at end of file diff --git a/home/.config/waybar/config-hypr b/home/.config/waybar/config-hypr new file mode 100644 index 0000000..62bfd1b --- /dev/null +++ b/home/.config/waybar/config-hypr @@ -0,0 +1,146 @@ +// vi: ft=json + +{ + "layer": "top", + "position": "top", + "height": 20, + + "modules-left": ["idle_inhibitor", "custom/gammastep", "hyprland/window"], + "modules-center": ["wlr/workspaces"], + "modules-right": ["pulseaudio", "pulseaudio#mic", "network#vpn", "network", "battery", "cpu", "memory", "clock", "tray"], + + "hyprland/window": { + "format": "{}", + "max-length": 70, + "separate-outputs": true, + "rewrite": { + "": "\uf015", + "(.*) — Mozilla Firefox": "\uf269 $1", + "Mozilla Firefox": "\uf269 Mozilla Firefox", + "Alacritty": "\uf120 Alacritty", + "(?:zsh;#toggleterm#1 - )?(.*) - N?VIM": "\uf15c $1", + "/(.*)": "\uf07b /$1", + "(.*) - mpv": "\uf03d $1", + "(.*) - Discord": "\uf392 $1", + "Stremio - (.*)": "\uf008 Stremio - $1", + "pulsemixer": "\uf001 Pulsemixer", + "Spotify": "\uf1bc Spotify", + } + }, + + "wlr/workspaces": { + "format": "{icon}", + "on-click": "activate", + "all-outputs": true, + "format-icons": { + "1": "", + "2": "", + "3": "", + "4": "", + "5": "", + "6": "", + "7": "7", + "8": "8", + "9": "9", + "urgent": "", + } + }, + + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "", + "deactivated": "" + } + }, + + "tray": { + "spacing": 10, + "show-passive-items": true + }, + + "clock": { + "format": "{:\uf017 %e %b %H:%M}", + "format-alt": "{:\uf133 %A, %d %B, %Y}", + "tooltip-format": "{:%d %B, %Y}\n{calendar}" + }, + + + "battery": { + "states": { + "warning": 30, + "critical": 15 + }, + "bat": "BAT0", + "adapter": "ADP0", + "format": "{icon} {capacity}%", + "format-charging": " {capacity}%", + "format-plugged": " {capacity}%", + "format-alt": "{icon} {time}", + "format-full": "", + "format-icons": ["", "", "", "", ""] + }, + + "network": { + "interval": 5, + "format-wifi": "\uf1eb", + "format-ethernet": "\uf796", + "format-disconnected": "\uf127 Offline", + "tooltip-format": "{ifname}: {ipaddr}", + "tooltip-format-wifi": "{essid} ({signalStrength}%): {ipaddr}" + }, + "network#vpn": { + "interval": 5, + "interface": "wgivpn", + "format": "\uf3ed", + "format-disconnected": "", + "tooltip-format": "VPN Connected: {ipaddr}" + }, + + "pulseaudio": { + "scroll-step": 1, + "format": "{icon} {volume}%", + "format-bluetooth": "{icon} {volume}%", + "format-bluetooth-muted": "{icon} ", + "format-muted": "", + "format-source": "", + "format-source-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pkill pulsemixer; alacritty -e pulsemixer" + }, + "pulseaudio#mic": { + "format": "{format_source}", + "format-source": "", + "format-source-muted": "", + "on-click": "pactl set-source-mute @DEFAULT_SOURCE@ toggle", + "tooltip": false + }, + + "custom/gammastep": { + "format": "{}", + "interval": 5, + "on-update": "", + "exec": "sleep 0.05; gammastep-ctl", + "on-click": "gammastep-ctl toggle" + }, + + "memory": { + "interval": 30, + "format": " {used:0.1f}G: {percentage}%", + }, + + "cpu": { + "interval": 10, + "format": " {}%", + "max-length": 10 + } + +} diff --git a/home/.config/waybar/config-hypr.bak b/home/.config/waybar/config-hypr.bak new file mode 100644 index 0000000..dc9801b --- /dev/null +++ b/home/.config/waybar/config-hypr.bak @@ -0,0 +1,159 @@ +{ + "layer": "top", // Waybar at top layer + "position": "top", // Waybar position (top|bottom|left|right) + "height": 30, // Waybar height (to be removed for auto height) + // "width": 1280, // Waybar width + "spacing": 4, // Gaps between modules (4px) + // Choose the order of the modules + "modules-left": ["wlr/workspaces"], + "modules-center": ["sway/window"], + "modules-right": ["idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "keyboard-state", "sway/language", "battery", "battery#bat2", "clock", "tray"], + // Modules configuration + // "sway/workspaces": { + // "disable-scroll": true, + // "all-outputs": true, + // "format": "{name}: {icon}", + // "format-icons": { + // "1": "", + // "2": "", + // "3": "", + // "4": "", + // "5": "", + // "urgent": "", + // "focused": "", + // "default": "" + // } + // }, + "keyboard-state": { + "numlock": true, + "capslock": true, + "format": "{name} {icon}", + "format-icons": { + "locked": "", + "unlocked": "" + } + }, + "sway/mode": { + "format": "{}" + }, + "mpd": { + "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ", + "format-disconnected": "Disconnected ", + "format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ", + "unknown-tag": "N/A", + "interval": 2, + "consume-icons": { + "on": " " + }, + "random-icons": { + "off": " ", + "on": " " + }, + "repeat-icons": { + "on": " " + }, + "single-icons": { + "on": "1 " + }, + "state-icons": { + "paused": "", + "playing": "" + }, + "tooltip-format": "MPD (connected)", + "tooltip-format-disconnected": "MPD (disconnected)" + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "", + "deactivated": "" + } + }, + "tray": { + // "icon-size": 21, + "spacing": 10 + }, + "clock": { + // "timezone": "America/New_York", + "tooltip-format": "{:%Y %B}\n{calendar}", + "format-alt": "{:%Y-%m-%d}" + }, + "cpu": { + "format": "{usage}% ", + "tooltip": false + }, + "memory": { + "format": "{}% " + }, + "temperature": { + // "thermal-zone": 2, + // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input", + "critical-threshold": 80, + // "format-critical": "{temperatureC}°C {icon}", + "format": "{temperatureC}°C {icon}", + "format-icons": ["", "", ""] + }, + "backlight": { + // "device": "acpi_video1", + "format": "{percent}% {icon}", + "format-icons": ["", "", "", "", "", "", "", "", ""] + }, + "battery": { + "states": { + // "good": 95, + "warning": 30, + "critical": 15 + }, + "format": "{capacity}% {icon}", + "format-charging": "{capacity}% ", + "format-plugged": "{capacity}% ", + "format-alt": "{time} {icon}", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": ["", "", "", "", ""] + }, + "battery#bat2": { + "bat": "BAT2" + }, + "network": { + // "interface": "wlp2*", // (Optional) To force the use of this interface + "format-wifi": "{essid} ({signalStrength}%) ", + "format-ethernet": "{ipaddr}/{cidr} ", + "tooltip-format": "{ifname} via {gwaddr} ", + "format-linked": "{ifname} (No IP) ", + "format-disconnected": "Disconnected ⚠", + "format-alt": "{ifname}: {ipaddr}/{cidr}" + }, + "pulseaudio": { + // "scroll-step": 1, // %, can be a float + "format": "{volume}% {icon} {format_source}", + "format-bluetooth": "{volume}% {icon} {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": " {format_source}", + "format-source": "{volume}% ", + "format-source-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pavucontrol" + }, + "custom/media": { + "format": "{icon} {}", + "return-type": "json", + "max-length": 40, + "format-icons": { + "spotify": "", + "default": "🎜" + }, + "escape": true, + "exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null" // Script in resources folder + // "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name + } +} + diff --git a/home/.config/waybar/style.css b/home/.config/waybar/style.css new file mode 100644 index 0000000..873768b --- /dev/null +++ b/home/.config/waybar/style.css @@ -0,0 +1,136 @@ +* { + border: none; + border-radius: 0; + font-family: "JetBrains Mono", "Font Awesome 6 Free"; + font-size: 14px; +} + +window .modules-left, +window .modules-center, +window .modules-right { + background: rgba(55, 59, 65, 0.85); + padding: 0px 8px 0px 8px; +} + +window .modules-left { + border-top-right-radius: 16px; + border-bottom-right-radius: 16px; +} + +window .modules-right { + border-top-left-radius: 16px; + border-bottom-left-radius: 16px; +} + +window .modules-center { + border-radius: 16px; +} +window#waybar { + background: transparent; +} + +window > box { + margin: 5px 0px 5px 0px; + padding: 0px 0px 0px 0px; + background: rgba(43, 48, 59, 0); + color: white; + border-radius: 16px; + min-height: 32px; +} + +#workspaces button { + font-weight: bolder; + margin: 3px; + padding: 0px 2px 0px 2px; + background-color: transparent; + color: rgba(255, 255, 255, 0.5); + min-width: 24px; + box-shadow: inset 0 -3px transparent; +} + +/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ +#workspaces button:hover { + background: transparent; + box-shadow: inset 0 -3px transparent; + color: rgba(255, 255, 255, 0.8); +} + +#workspaces button.active, +#workspaces button.focused { + background: transparent; + box-shadow: inset 0 -3px #ffffff; + color: rgba(255, 255, 255, 1); +} + +#workspaces button.urgent { + box-shadow: inset 0 -3px #cc6666; + color: #cc6666; +} + +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#custom-media, +#tray, +#mode, +#idle_inhibitor, +#mpd, +#window, +#workspaces, +#custom-gammastep +{ + padding: 0px 8px 0px 8px; + margin: 0 5px; + color: #ffffff; +} + +#mode { + font-weight: bolder; + color: #f0c674; +} + +#mpd.stopped { + color: rgba(255, 255, 255, 0.3); +} + +#idle_inhibitor.deactivated { + color: rgba(255, 255, 255, 0.3); +} + +#network.disconnected, #network.disabled { + color: rgba(255, 255, 255, 0.3); +} + +#clock { + font-weight: bolder; +} + +@keyframes blink { + to { + color: #ffffff; + } +} + +#battery.critical:not(.charging) { + /* background-color: #f53c3c; */ + color: #ffffff; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; +} diff --git a/home/.config/wget/wgetrc b/home/.config/wget/wgetrc new file mode 100644 index 0000000..4fd7999 --- /dev/null +++ b/home/.config/wget/wgetrc @@ -0,0 +1 @@ +hsts-file=~/.cache/wget-hsts diff --git a/home/.config/wireplumber/main.lua.d/51-device-rename.lua b/home/.config/wireplumber/main.lua.d/51-device-rename.lua new file mode 100644 index 0000000..27cdaf9 --- /dev/null +++ b/home/.config/wireplumber/main.lua.d/51-device-rename.lua @@ -0,0 +1,59 @@ + +table.insert( + alsa_monitor.rules, + { + matches = { + { + { "node.name", "equals", "alsa_output.pci-0000_05_00.6.analog-stereo" }, + }, + }, + apply_properties = { + ["node.description"] = "Laptop-output", + }, + } +) + +table.insert( + alsa_monitor.rules, + { + matches = { + { + { "node.name", "equals", "alsa_input.pci-0000_05_00.6.analog-stereo" }, + }, + }, + apply_properties = { + ["node.description"] = "Laptop-input", + }, + } +) + + +table.insert( + alsa_monitor.rules, + { + matches = { + { + { "node.name", "equals", "alsa_input.usb-C-Media_Electronics_Inc._Bloody_Gaming_Audio_Device-00.analog-stereo" }, + }, + }, + apply_properties = { + ["node.description"] = "Bloody_Gaming_Headphones-input", + }, + } +) + + +table.insert( + alsa_monitor.rules, + { + matches = { + { + { "node.name", "equals", "alsa_output.usb-C-Media_Electronics_Inc._Bloody_Gaming_Audio_Device-00.analog-stereo" }, + }, + }, + apply_properties = { + ["node.description"] = "Bloody_Gaming_Headphones-output", + }, + } +) + diff --git a/home/.config/wofi/config b/home/.config/wofi/config new file mode 100644 index 0000000..9217ff5 --- /dev/null +++ b/home/.config/wofi/config @@ -0,0 +1,7 @@ +width=40% +height=30% +show=drun +prompt=Search +allow_images=true +allow_markup=true +insensitive=true diff --git a/home/.config/wofi/style.css b/home/.config/wofi/style.css new file mode 100644 index 0000000..0ef36a6 --- /dev/null +++ b/home/.config/wofi/style.css @@ -0,0 +1,51 @@ +window { + font-family: "DejaVu Sans", "Font Awesome 5 Free"; + margin: 0px; + border: 1px solid rgba(0, 0, 0, 0.9); + background-color: rgba(29, 31, 33, 0.95); + border-radius: 10px; +} + +#input { + margin: 5px; + border: none; + color: #f8f8f2; + background-color: rgba(55, 59, 65, 0.95); +} + +#inner-box { + margin: 5px; + border: none; + background-color: transparent; +} + +#outer-box { + margin: 5px; + border: none; + background-color: transparent; +} + +#scroll { + margin: 0px; + border: none; +} + +#text { + margin: 5px; + border: none; + color: #c5c8c6; +} + +#entry { + border: none; +} + +#entry:focus { + border: none; +} + +#entry:selected { + background-color: rgba(55, 59, 65, 0.95); + border-radius: 5px; + border: none; +} diff --git a/home/.config/zsh/.zprofile b/home/.config/zsh/.zprofile new file mode 120000 index 0000000..5046066 --- /dev/null +++ b/home/.config/zsh/.zprofile @@ -0,0 +1 @@ +../shell/profile \ No newline at end of file diff --git a/home/.config/zsh/.zshenv b/home/.config/zsh/.zshenv new file mode 120000 index 0000000..d8e764c --- /dev/null +++ b/home/.config/zsh/.zshenv @@ -0,0 +1 @@ +../shell/environment \ No newline at end of file diff --git a/home/.config/zsh/.zshrc b/home/.config/zsh/.zshrc new file mode 100755 index 0000000..9182e4b --- /dev/null +++ b/home/.config/zsh/.zshrc @@ -0,0 +1,75 @@ +#!/usr/bin/zsh + +# ZSH Options +setopt auto_cd # cd by typing directory name if it's not a command +setopt auto_list # automatically list choices on ambiguous completion +setopt auto_menu # automatically use menu completion +setopt always_to_end # move cursor to end if word had one match +setopt interactivecomments # allow comments in interactive mode +setopt magicequalsubst # enable filename expansion for arguments of form `x=expression` +setopt notify # report the status of background jobs immediately +setopt numericglobsort # sort filenames numerically when it makes sense +setopt auto_pushd # Make cd act as pushd +#setopt correct_all # autocorrect commands + +# oh-my-zsh configuration (DISABLED by default, if you want oh-my-zsh, uncomment these) +#export ZSH="/usr/share/oh-my-zsh" +#ZSH_THEME="af-magic" +#UPDATE_ZSH_DAYS=8 +#ENABLE_CORRECTION="false" +#source $ZSH/oh-my-zsh.sh # Run oh-my-zsh + +# ZSH files setup (don't clutter home) +export ZSH_CACHE="$HOME/.cache/zsh" +export HISTFILE="$ZSH_CACHE/history" +export ZSH_COMPDUMP="$ZSH_CACHE/zcompdump-$ZSH_VERSION" +mkdir -p "$ZSH_CACHE" + +# Auto-remove home clutter +[ -f ~/.zsh-update ] && mv ~/.zsh-update $ZSH_CACHE/.zsh-update +[ -f ~/.sudo_as_admin_sucessful ] && rm ~/.sudo_as_admin_successful +[ -f ~/.bash_history ] && rm ~/.bash_history + +# History configuration +export HISTSIZE=10000 +export SAVEHIST=10000 +setopt appendhistory # save history entries as soon as they are entered +setopt hist_ignore_space # ignore commands that start with space +setopt hist_verify # show commands with history expansion to user before running it +setopt extended_history # record command start time +#setopt hist_ignore_dups # ignore duplicated commands history list +#setopt hist_expire_dups_first # delete duplicates first when HISTFILE size exceeds HISTFILE +#setopt share_history # share command history data between terminals + +# Completion features (tab) +autoload -Uz compinit +zmodload -i zsh/complist # load completion list +compinit -d $ZSH_COMPDUMP # Specify compdump file +comp_options+=(globdots) # Enable completion on hidden files. +zstyle ':completion:*' menu select # select completions with arrow keys +zstyle ':completion:*' group-name '' # group results by category +zstyle ':completion:::::' completer _expand _complete _ignored _approximate #enable approximate matches for completion + +# Color support +#autoload -U colors && colors + +# Setup aliases +[ -f ~/.config/shell/aliases ] && source ~/.config/shell/aliases +# Load handlers +[ -f ~/.config/shell/handlers ] && source ~/.config/shell/handlers +# Load key bindings +[ -f ~/.config/shell/keybinds ] && source ~/.config/shell/keybinds +# Load prompt +[ -f ~/.config/shell/prompt ] && source ~/.config/shell/prompt + +# Define TMOUT timeout for TTY and root +[ -z "$DISPLAY" ] && export TMOUT=800 +[ $UID -eq 0 ] && export TMOUT=600 + +# Load extensions (should be last) +source /usr/share/zsh/site-functions/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh +source /usr/share/zsh/site-functions/zsh-autosuggestions/zsh-autosuggestions.zsh +source /usr/local/src/z.lua/z.lua.plugin.zsh +if command -v pyenv >/dev/null 2>&1; then + eval "$(pyenv init -)" +fi diff --git a/home/.local/bin/npm/lib/.keep b/home/.local/bin/npm/lib/.keep new file mode 100644 index 0000000..e69de29 diff --git a/home/.local/bin/scripts/cli/bitcoin b/home/.local/bin/scripts/cli/bitcoin new file mode 100755 index 0000000..d5547e8 --- /dev/null +++ b/home/.local/bin/scripts/cli/bitcoin @@ -0,0 +1,12 @@ +#!/bin/sh + +BTC_DATA=$(curl https://api.coindesk.com/v1/bpi/currentprice.json 2>/dev/null || echo 'ERR') + +if [ "$BTC_DATA" != "ERR" ]; then + BTC_PRICE=$(echo $BTC_DATA | jq -r ".bpi.USD.rate_float") + BTC_PRICE=$(printf "%.0f" "$BTC_PRICE") + echo \$"$BTC_PRICE" +else + echo "N/A" +fi + diff --git a/home/.local/bin/scripts/cli/cheat.sh b/home/.local/bin/scripts/cli/cheat.sh new file mode 100755 index 0000000..38bbdf9 --- /dev/null +++ b/home/.local/bin/scripts/cli/cheat.sh @@ -0,0 +1,111 @@ +#!/bin/sh + +# rm_trailing_slashes(string) +# +# Prints a string without any trailing slashes. +# This is used because cheat.sh doesn't play nicely with multiple slashes in +# URLs. +rm_trailing_slashes() { + string="$1" + last_char="$(printf "$string" | tail -c 1)" + if [ "$last_char" = "/" ]; then + echo "$(rm_trailing_slashes "${string%?}")" + else + echo "$string" + fi +} + +# pick_category(must_match, query, argument, recurse) +# +# Pick cheat.sh category. +# if must_match is 1, only allow listed options to be picked. +# if query is specified, pick sub-category of it, else pick global categories. +# if argument is specified, optionally perform must_match check and print it. +# if recurse is 1, if the selected option ends with /, run the function again. +# +# Prints the chosen category +pick_category() { + must_match="$1" + query="$(rm_trailing_slashes "$2")" + argument="$3" + recurse="$4" + + # Query all possible options + if [ -n "$query" ]; then + url="cheat.sh/$query/:list" + else + url="cheat.sh/:list" + fi + selectable="$(curl -s "$url")" + + # If argument is specified, print it, optionally perform must_match check. + if [ -n "$argument" ]; then + if [ "$must_match" -ne 1 ] || echo "$selectable" | grep -qe "\b$1\b"; then + selected="$argument" + else + echo "Invalid selection: '$argument'" + echo "For all selections, query $url" + exit 1 + fi + # Select the option with fzf, optionally allow other matches if must_match isn't set. + else + if [ "$must_match" -ne 1 ]; then + if [ -z "$selectable" ]; then + header="No selections found, you can use empty query to show category help, or type a custom query." + else + header="Use alt-enter to enter non-listed query. You can use empty queries to show category help." + fi + selected="$(printf "\n$selectable" | \ + fzf --bind=alt-enter:print-query \ + --print-query \ + --prompt="cheat.sh/$query query>" \ + --header="$header"\ + )" + else + selected=$(printf "$selectable" | fzf --prompt="cheat.sh/$query category>") + if [ $? -ne 0 ]; then + echo "Invalid selection: '$selected'" + echo "For all selections, query $url" + exit 1 + fi + fi + selected=$(printf "$selected" | tail -1) + fi + + + # Replace spaces with '+' (cheat.sh resolves those as spaces) + selected="$(echo "$selected" | tr ' ' '+')" + + # Prepend the original query, if we have one + # Print the selected category, or subcategory with the category + if [ -n "$query" ]; then + result="$query/$selected" + else + result="$selected" + fi + + # Recurse, if specified and the result ended with / + if [ "$recurse" -eq 1 ]; then + if [ "$(printf "$selected" | tail -c 1)" = "/" ]; then + result="$(pick_category "$must_match" "$result" "$argument" 1)" + fi + fi + + # Print the result + printf "$result" +} + +# Select the cheatsheat category (language/core-util/...) +query=$(pick_category 1 "" "$1" 0) + +# If the query isn't already complete, select a sub-category +if ! echo "$query" | grep -qe ":"; then + query="$(pick_category 0 "$query" "$2" 1)" +fi + +# Construct the URL from given query and print it +url="cheat.sh/$query" +echo "$url" + +# Show the output of cheat.sh request +curl -s "$url" diff --git a/home/.local/bin/scripts/cli/colors-256 b/home/.local/bin/scripts/cli/colors-256 new file mode 100755 index 0000000..109fba1 --- /dev/null +++ b/home/.local/bin/scripts/cli/colors-256 @@ -0,0 +1,102 @@ +#!/bin/bash + +# # Print out 256 colors, with each number printed in its corresponding colour +# +# This file is uploaded on +# It was originally intended to be used as an alias that curled this URL and piped it into bash, however +# this is very unsafe as the owner can change the content of this gist at his convenience, meaning it was +# a potential security vulnerability. This is a script version of this alias to avoid this issue. +# +# The copyright for this file belongs to the original author: Tom Hale, 2016 +# This file was released under MIT license + +set -eu # Fail on errors or undeclared variables + +printable_colours=256 + +# Return a colour that contrasts with the given colour +# Bash only does integer division, so keep it integral +function contrast_colour { + local r g b luminance + colour="$1" + + if (( colour < 16 )); then # Initial 16 ANSI colours + (( colour == 0 )) && printf "15" || printf "0" + return + fi + + # Greyscale # rgb_R = rgb_G = rgb_B = (number - 232) * 10 + 8 + if (( colour > 231 )); then # Greyscale ramp + (( colour < 244 )) && printf "15" || printf "0" + return + fi + + # All other colours: + # 6x6x6 colour cube = 16 + 36*R + 6*G + B # Where RGB are [0..5] + # See http://stackoverflow.com/a/27165165/5353461 + + # r=$(( (colour-16) / 36 )) + g=$(( ((colour-16) % 36) / 6 )) + # b=$(( (colour-16) % 6 )) + + # If luminance is bright, print number in black, white otherwise. + # Green contributes 587/1000 to human perceived luminance - ITU R-REC-BT.601 + (( g > 2)) && printf "0" || printf "15" + return + + # Uncomment the below for more precise luminance calculations + + # # Calculate percieved brightness + # # See https://www.w3.org/TR/AERT#color-contrast + # # and http://www.itu.int/rec/R-REC-BT.601 + # # Luminance is in range 0..5000 as each value is 0..5 + # luminance=$(( (r * 299) + (g * 587) + (b * 114) )) + # (( $luminance > 2500 )) && printf "0" || printf "15" +} + +# Print a coloured block with the number of that colour +function print_colour { + local colour="$1" contrast + contrast=$(contrast_colour "$1") + printf "\e[48;5;%sm" "$colour" # Start block of colour + printf "\e[38;5;%sm%3d" "$contrast" "$colour" # In contrast, print number + printf "\e[0m " # Reset colour +} + +# Starting at $1, print a run of $2 colours +function print_run { + local i + for (( i = "$1"; i < "$1" + "$2" && i < printable_colours; i++ )) do + print_colour "$i" + done + printf " " +} + +# Print blocks of colours +function print_blocks { + local start="$1" i + local end="$2" # inclusive + local block_cols="$3" + local block_rows="$4" + local blocks_per_line="$5" + local block_length=$((block_cols * block_rows)) + + # Print sets of blocks + for (( i = start; i <= end; i += (blocks_per_line-1) * block_length )) do + printf "\n" # Space before each set of blocks + # For each block row + for (( row = 0; row < block_rows; row++ )) do + # Print block columns for all blocks on the line + for (( block = 0; block < blocks_per_line; block++ )) do + print_run $(( i + (block * block_length) )) "$block_cols" + done + (( i += block_cols )) # Prepare to print the next row + printf "\n" + done + done +} + +print_run 0 16 # The first 16 colours are spread over the whole spectrum +printf "\n" +print_blocks 16 231 6 6 3 # 6x6x6 colour cube between 16 and 231 inclusive +print_blocks 232 255 12 2 1 # Not 50, but 24 Shades of Grey diff --git a/home/.local/bin/scripts/cli/lfu b/home/.local/bin/scripts/cli/lfu new file mode 100755 index 0000000..224f19b --- /dev/null +++ b/home/.local/bin/scripts/cli/lfu @@ -0,0 +1,24 @@ +#!/bin/sh +set -e + +if [ -n "$DISPLAY" ]; then + export FIFO_UEBERZUG="${TMPDIR:-/tmp}/lf-ueberzug-$$" + + cleanup() { + exec 3>&- + rm "$FIFO_UEBERZUG" + } + + mkfifo "$FIFO_UEBERZUG" + ueberzug layer -s <"$FIFO_UEBERZUG" & + exec 3>"$FIFO_UEBERZUG" + trap cleanup EXIT + + if ! [ -d "$HOME/.cache/lf" ]; then + mkdir -p "$HOME/.cache/lf" + fi + + lf "$@" 3>&- +else + exec lf "$@" +fi diff --git a/home/.local/bin/scripts/extra/unix b/home/.local/bin/scripts/extra/unix new file mode 100755 index 0000000..a9fb96e --- /dev/null +++ b/home/.local/bin/scripts/extra/unix @@ -0,0 +1,26 @@ +#!/bin/sh + +#original artwork by http://www.sanderfocus.nl/#/portfolio/tech-heroes +#converted to shell by #nixers @ irc.unix.chat + +cat << 'eof' + ,_ ,_==▄▂ + , ▂▃▄▄▅▅▅▂▅¾. / / + ▄▆<´ "»▓▓▓%\ / / / / + ,▅7" ´>▓▓▓% / / > / >/% + ▐¶▓ ,»▓▓¾´ /> %/%// / / + ▓▃▅▅▅▃,,▄▅▅▅Æ\// ///>// />/ / + V║«¼.;→ ║<«.,`=// />//%/% / / + //╠<´ -²,)(▓~"-╝/¾/ %/>/ /> + / / / ▐% -./▄▃▄▅▐, /7//;//% / / + / ////`▌▐ %zWv xX▓▇▌//&;% / / + / / / %//%/¾½´▌▃▄▄▄▄▃▃▐¶\/& / + </ /)VY>7; \_ UNIX IS VERY SIMPLE IT JUST NEEDS A + / /</ //<///<_/%\▓ V%W%£)XY _/%‾\_, GENIUS TO UNDERSTAND ITS SIMPLICITY + / / //%/_,=--^/%/%%\¾%¶%%} /%%%%%%;\, + %/< /_/ %%%%%;X%%\%%;, _/%%%;, \ + / / %%%%%%;, \%%l%%;// _/%;, dmr + / %%%;, <;\-=-/ / + ;, l +eof diff --git a/home/.local/bin/scripts/gui/brightness b/home/.local/bin/scripts/gui/brightness new file mode 100755 index 0000000..4efadf0 --- /dev/null +++ b/home/.local/bin/scripts/gui/brightness @@ -0,0 +1,153 @@ +#!/bin/sh + + +# Parse arguments +# ------------------------------------------------------------------------------------ +BRIGHTNESS_DIR="/sys/class/backlight/*" +SEND_NOTIFICATION=0 +URGENCY="normal" +INCREASE=0 +DECREASE=0 +SET=0 +BRIGHTNESS=0 + +while [ "$1" ]; do + case "$1" in + -h | --help) + cat << EOF +brightness is a cli tool that for displaying or modifying screen brightness. + +Options: +-h | --help: Display this message +-n | --notification: Produce a desktop notification with brightness info +-N | --no-notification: Don't produce a desktop notification with brightness info +-u | --urgency [URGENCY]: Pass over notify-send urgency attribute (default: normal) +-i | --increase [BRIGHTNESS]: Increase the brightness by given amount +-d | --decrease [BRIGHTNESS]: Decrease the brightness by given amount +-s | --set [BRIGHTNESS]: Set new brightness level +-p | --path [DIR_PATH]: Path to brightness directory (default: /sys/class/backlight/*) + +Valid values: + URGENCY: low, normal, critical + DIR_PATH: Valid path to a directory + BRIGHTNESS: + specific value - Example: 10 + percentage value - Example: 10% +EOF + exit 0 + ;; + -n | --notification) + SEND_NOTIFICATION=1 + ;; + -N | --no-notification) + SEND_NOTIFICATION=0 + ;; + -u | --urgency) + URGENCY="$2" + shift + ;; + -i | --increase) + INCREASE=1 + BRIGHTNESS="$2" + shift + ;; + -d | --decrease) + DECREASE=1 + BRIGHTNESS="$2" + shift + ;; + -s | --set) + SET=1 + BRIGHTNESS="$2" + shift + ;; + -p | --path) + BRIGHTNESS_DIR="$2" + shift + ;; + * ) + echo "Unknown argument '$1', use -h or --help for help" + exit 1 + ;; + esac + shift +done + +# Define constants based on parsed arguments +# ------------------------------------------------------------------------------------ +BRIGHTNESS_FILE="$BRIGHTNESS_DIR/brightness" +BRIGHTNESS_MAX="$(cat $BRIGHTNESS_DIR/max_brightness)" + + +# Helper functins +# ------------------------------------------------------------------------------------ + +# Send brightness level desktop notification, showing the given brightness level +# as progress bar, along with given message. +# $1 - brightness level (number 0-100) +# $2 - message (notification body) +send_brightness_notify() { + percent_brightness="$1" + msg="$2" + + notify-send \ + --app-name=brightness \ + --urgency="$URGENCY" \ + -h int:value:$percent_brightness \ + -h string:synchronous:brightness \ + "brightness" "$msg" +} + + +# Set brightness to given absolute value +# $1 - brightness absolute value +set_brightness() { + # there should be sudo config allowing this command without password + echo "$1" | sudo tee $BRIGHTNESS_FILE >/dev/null +} + + +# Main Logic +# ------------------------------------------------------------------------------------ + +# Determine the absolute new brightness level +if [ $INCREASE -eq 1 ] || [ $DECREASE -eq 1 ] || [ $SET -eq 1 ]; then + # If we're dealing with percentages, change to absolutes + if echo "$BRIGHTNESS" | grep -qE '%$'; then + numeric=$(echo "$BRIGHTNESS" | sed 's/.$//') + absolute=$(echo "($BRIGHTNESS_MAX / 100) * $numeric" | bc -l) + BRIGHTNESS=$(printf "%.0f" $absolute) + fi + + # Get the new requested absolute brightness + if [ $SET -eq 1 ]; then + new_brightness=$BRIGHTNESS + elif [ $DECREASE -eq 1 ]; then + cur_brightness=$(cat $BRIGHTNESS_FILE) + new_brightness=$(($cur_brightness - $BRIGHTNESS)) + else + cur_brightness=$(cat $BRIGHTNESS_FILE) + new_brightness=$(($cur_brightness + $BRIGHTNESS)) + fi + + # Ensure we respect max/min boundaries + if [ $new_brightness -lt 0 ]; then + new_brightness=0 + elif [ $new_brightness -gt $BRIGHTNESS_MAX ]; then + new_brightness=$BRIGHTNESS_MAX + fi + + # Update the brightness + set_brightness $new_brightness +fi + +cur_brightness=$(cat $BRIGHTNESS_FILE) +percent_brightness=$(echo "($cur_brightness / $BRIGHTNESS_MAX) * 100" | bc -l) +percent_brightness_2f=$(printf "%.2f" $percent_brightness) +percent_brightness_rounded=$(printf "%.0f" $percent_brightness) + +if [ $SEND_NOTIFICATION -eq 1 ]; then + send_brightness_notify "$percent_brightness_rounded" "Level: $percent_brightness_rounded" +fi + +echo "Brightness: ${percent_brightness_2f}% (absolute: $cur_brightness)" diff --git a/home/.local/bin/scripts/gui/deskopen b/home/.local/bin/scripts/gui/deskopen new file mode 100755 index 0000000..98d8280 --- /dev/null +++ b/home/.local/bin/scripts/gui/deskopen @@ -0,0 +1,11 @@ +#!/bin/sh + +# Find the line with exec, if there's multiple lines +# use the last one +exec_line=$(grep '^Exec' "$1" | tail -1) +# Remove 'Exec' and arguments (%u, %f, ...) +cmd=$(echo $exec_line | sed 's/^Exec=//' | sed 's/%.//') +# Remove "" around command (if present) +cmd=$(echo $cmd | sed 's/^"//g' | sed 's/" *$//g') +# Run the exec line of the application using /bin/sh +/bin/sh -c "$cmd" diff --git a/home/.local/bin/scripts/gui/dmenu b/home/.local/bin/scripts/gui/dmenu new file mode 100755 index 0000000..f58a2e5 --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu @@ -0,0 +1,9 @@ +#!/bin/sh + +# Compatibility executable script for applications running dmenu, which +# runs wofi in dmenu mode instead. Note: In many cases the arguments won't +# be compatible and this will fail, however the primary way scripts use +# dmenu is just for simple prompts, using the `-p` flag. and wofi does fully +# support this usage. + +cat | wofi --dmenu $@ diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/displayselect b/home/.local/bin/scripts/gui/dmenu-scripts/displayselect new file mode 100755 index 0000000..8d7997c --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/displayselect @@ -0,0 +1,85 @@ + +#!/bin/sh + +# A UI for detecting and selecting all displays. Probes xrandr for connected +# displays and lets user select one to use. User may also select "manual +# selection" which opens arandr. + +twoscreen() { # If multi-monitor is selected and there are two screens. + + mirror=$(printf "no\\nyes" | dmenu -i -p "Mirror displays?") + # Mirror displays using native resolution of external display and a scaled + # version for the internal display + if [ "$mirror" = "yes" ]; then + external=$(echo "$screens" | dmenu -i -p "Optimize resolution for:") + internal=$(echo "$screens" | grep -v "$external") + + res_external=$(xrandr --query | sed -n "/^$external/,/\+/p" | \ + tail -n 1 | awk '{print $1}') + res_internal=$(xrandr --query | sed -n "/^$internal/,/\+/p" | \ + tail -n 1 | awk '{print $1}') + + res_ext_x=$(echo "$res_external" | sed 's/x.*//') + res_ext_y=$(echo "$res_external" | sed 's/.*x//') + res_int_x=$(echo "$res_internal" | sed 's/x.*//') + res_int_y=$(echo "$res_internal" | sed 's/.*x//') + + scale_x=$(echo "$res_ext_x / $res_int_x" | bc -l) + scale_y=$(echo "$res_ext_y / $res_int_y" | bc -l) + + xrandr --output "$external" --auto --scale 1.0x1.0 \ + --output "$internal" --auto --same-as "$external" \ + --scale "$scale_x"x"$scale_y" + else + + primary=$(echo "$screens" | dmenu -i -p "Select primary display:") + secondary=$(echo "$screens" | grep -v "$primary") + direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?") + xrandr --output "$primary" --auto --scale 1.0x1.0 --output "$secondary" --"$direction"-of "$primary" --auto --scale 1.0x1.0 + fi + } + +morescreen() { # If multi-monitor is selected and there are more than two screens. + primary=$(echo "$screens" | dmenu -i -p "Select primary display:") + secondary=$(echo "$screens" | grep -v "$primary" | dmenu -i -p "Select secondary display:") + direction=$(printf "left\\nright" | dmenu -i -p "What side of $primary should $secondary be on?") + tertiary=$(echo "$screens" | grep -v "$primary" | grep -v "$secondary" | dmenu -i -p "Select third display:") + xrandr --output "$primary" --auto --output "$secondary" --"$direction"-of "$primary" --auto --output "$tertiary" --"$(printf "left\\nright" | grep -v "$direction")"-of "$primary" --auto + } + +multimon() { # Multi-monitor handler. + case "$(echo "$screens" | wc -l)" in + 2) twoscreen ;; + *) morescreen ;; + esac ;} + +onescreen() { # If only one output available or chosen. + xrandr --output "$1" --auto --scale 1.0x1.0 $(echo "$allposs" | grep -v "\b$1" | awk '{print "--output", $1, "--off"}' | paste -sd ' ' -) + } + +postrun() { # Stuff to run to clean up. + command -v setbg >/dev/null && setbg # Fix background if screen size/arangement has changed. + } + +# Get all possible displays +allposs=$(xrandr -q | grep "connected") + +# Get all connected screens. +screens=$(echo "$allposs" | awk '/ connected/ {print $1}') + +# If there's only one screen +if [ "$(echo "$screens" | wc -l)" -lt 2 ]; then + onescreen "$screens" + notify-send "💻 Only one screen detected." "Using it in its optimal settings..." +else + # Get user choice including multi-monitor and manual selection: + chosen=$(printf "%s\\nmulti-monitor\\nmanual selection" "$screens" | dmenu -i -p "Select display arangement:") && + case "$chosen" in + "manual selection") arandr ; exit ;; + "multi-monitor") multimon ;; + *) onescreen "$chosen" ;; + esac +fi + + +postrun diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/dman b/home/.local/bin/scripts/gui/dmenu-scripts/dman new file mode 100755 index 0000000..fdcb93e --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/dman @@ -0,0 +1,11 @@ +#!/bin/sh + +# Dmenu prompt to easily search for a man page to open + +page="$(apropos --long "$1" | dmenu -i -l 10 | awk '{print $2, $1}' | tr -d '()')" + +if tty -s; then + man $page +else + $TERMINAL -e man $page +fi diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/dmenumount b/home/.local/bin/scripts/gui/dmenu-scripts/dmenumount new file mode 100755 index 0000000..2793633 --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/dmenumount @@ -0,0 +1,68 @@ +#!/bin/sh + +# Gives dmenu prompt to mount unmounted drives and Android phones. +# If they're in /etc/fstab they'll be mounted automatically. +# Otherwise, you'll be prompted to give a mountpoint from already +# existing directories. If you input a novel directory, it will +# prompt you to create that directory. + +getmount() { \ + [ -z "$chosen" ] && exit 1 + # shellcheck disable=SC2086 + mp="$(find $1 2>/dev/null | dmenu -i -p "Type in mount point.")" || exit 1 + test -z "$mp" && exit 1 + if [ ! -d "$mp" ]; then + mkdiryn=$(printf "No\\nYes" | dmenu -i -p "$mp does not exist. Create it?") || exit 1 + [ "$mkdiryn" = "Yes" ] && (mkdir -p "$mp" || sudo -A mkdir -p "$mp") + fi + } + +mountusb() { \ + chosen="$(echo "$usbdrives" | dmenu -i -p "Mount which drive?")" || exit 1 + chosen="$(echo "$chosen" | awk '{print $1}')" + sudo -A mount "$chosen" 2>/dev/null && notify-send "💻 USB mounting" "$chosen mounted." && exit 0 + alreadymounted=$(lsblk -nrpo "name,type,mountpoint" | awk '$3!~/\/boot|\/home$|SWAP/&&length($3)>1{printf "-not ( -path *%s -prune ) ",$3}') + getmount "/mnt /media /mount /home -maxdepth 5 -type d $alreadymounted" + partitiontype="$(lsblk -no "fstype" "$chosen")" + case "$partitiontype" in + "vfat") sudo -A mount -t vfat "$chosen" "$mp" -o rw,umask=0000;; + "exfat") sudo -A mount "$chosen" "$mp" -o uid="$(id -u)",gid="$(id -g)";; + *) sudo -A mount "$chosen" "$mp"; user="$(whoami)"; ug="$(groups | awk '{print $1}')"; sudo -A chown "$user":"$ug" "$mp";; + esac + notify-send "💻 USB mounting" "$chosen mounted to $mp." + } + +mountandroid() { \ + chosen="$(echo "$anddrives" | dmenu -i -p "Which Android device?")" || exit 1 + chosen="$(echo "$chosen" | cut -d : -f 1)" + getmount "$HOME -maxdepth 3 -type d" + simple-mtpfs --device "$chosen" "$mp" + echo "OK" | dmenu -i -p "Tap Allow on your phone if it asks for permission and then press enter" || exit 1 + simple-mtpfs --device "$chosen" "$mp" + notify-send "🤖 Android Mounting" "Android device mounted to $mp." + } + +asktype() { \ + choice="$(printf "USB\\nAndroid" | dmenu -i -p "Mount a USB drive or Android device?")" || exit 1 + case $choice in + USB) mountusb ;; + Android) mountandroid ;; + esac + } + +anddrives=$(simple-mtpfs -l 2>/dev/null) +usbdrives="$(lsblk -rpo "name,type,size,mountpoint" | grep 'part\|rom' | awk '$4==""{printf "%s (%s)\n",$1,$3}')" + +if [ -z "$usbdrives" ]; then + [ -z "$anddrives" ] && echo "No USB drive or Android device detected" && exit + echo "Android device(s) detected." + mountandroid +else + if [ -z "$anddrives" ]; then + echo "USB drive(s) detected." + mountusb + else + echo "Mountable USB drive(s) and Android device(s) detected." + asktype + fi +fi diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/dmenupass b/home/.local/bin/scripts/gui/dmenu-scripts/dmenupass new file mode 100755 index 0000000..8d5ce30 --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/dmenupass @@ -0,0 +1,6 @@ +#!/bin/sh + +# This script is the value for SUDO_ASKPASS variable, +# meaning that it will be used as a password prompt if needed. + +dmenu -P -p "$1" diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/dmenuprompt b/home/.local/bin/scripts/gui/dmenu-scripts/dmenuprompt new file mode 100755 index 0000000..4d0adec --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/dmenuprompt @@ -0,0 +1,22 @@ +#!/bin/sh + +# Opens a basic yes/no prompt with dmenu +# This is useful for confirming whether an action should be taken + +# First try to run with restrict (-r) flag +# however not everyone has this patch applied, so if that fails, fall back +out="$(printf "No\nYes" | dmenu -i -r -p "$1" 2>/dev/null)" +if [ $? -ne 0 ]; then + out="$(printf "No\nYes" | dmenu -i -p "$1")" +fi + + +if [ "$out" == "Yes" ]; then + exit 0 +elif [ "$out" == "No" ]; then + exit 1 +else + # Dmenu allows invalid picks by explicitly typing in a different option + # when that happens, end with code 2 instead. + exit 2 +fi diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/dmenurecord b/home/.local/bin/scripts/gui/dmenu-scripts/dmenurecord new file mode 100755 index 0000000..60ce8dc --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/dmenurecord @@ -0,0 +1,121 @@ + +#!/bin/sh + +# Usage: +# `$0`: Ask for recording type via dmenu +# `$0 screencast`: Record both audio and screen +# `$0 video`: Record only screen +# `$0 audio`: Record only audio +# `$0 kill`: Kill existing recording +# +# If there is already a running instance, user will be prompted to end it. + +screencast() { + ffmpeg -y \ + -f x11grab \ + -framerate 60 \ + -s "$(xdpyinfo | grep dimensions | awk '{print $2;}')" \ + -i "$DISPLAY" \ + -f alsa -i default \ + -r 30 \ + -c:v h264 -crf 0 -preset ultrafast -c:a aac \ + "$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mp4" & + echo $! > /tmp/recordingpid +} + +video() { + ffmpeg \ + -f x11grab \ + -s "$(xdpyinfo | grep dimensions | awk '{print $2;}')" \ + -i "$DISPLAY" \ + -c:v libx264 -qp 0 -r 30 \ + "$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid +} + +webcamhidef() { + ffmpeg \ + -f v4l2 \ + -i /dev/video0 \ + -video_size 1920x1080 \ + "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid +} + +webcam() { + ffmpeg \ + -f v4l2 \ + -i /dev/video0 \ + -video_size 640x480 \ + "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid +} + + +audio() { + ffmpeg \ + -f alsa -i default \ + "$HOME/audio-$(date '+%y%m%d-%H%M-%S').mp3" & + echo $! > /tmp/recordingpid +} + +asktoend() { + response=$(printf "No\\nYes" | dmenu -i -p "Recording still active. End recording?") && + [ "$response" = "Yes" ] && killrecording +} + +videoselected() +{ + slop -f "%x %y %w %h" > /tmp/slop + read -r X Y W H < /tmp/slop + rm /tmp/slop + + ffmpeg \ + -f x11grab \ + -framerate 60 \ + -video_size "$W"x"$H" \ + -i :0.0+"$X,$Y" \ + -c:v libx264 -qp 0 -r 30 \ + "$HOME/box-$(date '+%y%m%d-%H%M-%S').mkv" & + echo $! > /tmp/recordingpid +} + +killrecording() { + recpid="$(cat /tmp/recordingpid)" + # kill with SIGTERM, allowing finishing touches. + kill -15 "$recpid" 2>/dev/null + rm -f /tmp/recordingpid + # even after SIGTERM, ffmpeg may still run, so SIGKILL it. + sleep 3 + kill -9 "$recpid" 2>/dev/null + exit +} + +askrecording() { \ + choice=$(printf "screencast\\nvideo\\nvideo selected\\naudio\\nwebcam\\nwebcam (hi-def)" | dmenu -i -p "Select recording style:") + case "$choice" in + screencast) screencast;; + audio) audio;; + video) video;; + *selected) videoselected;; + webcam) webcam;; + "webcam (hi-def)") webcamhidef;; + esac +} + +case "$1" in + screencast) screencast;; + audio) audio;; + video) video;; + *selected) videoselected;; + kill) killrecording;; + *) + if [ -f /tmp/recordingpid ]; then + recpid="$(cat /tmp/recordingpid)" + if ps -p $recpid > /dev/null; then + asktoend + exit + fi + fi + askrecording;; +esac diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/dmenuumount b/home/.local/bin/scripts/gui/dmenu-scripts/dmenuumount new file mode 100755 index 0000000..26612ef --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/dmenuumount @@ -0,0 +1,44 @@ +#!/bin/sh + +# A dmenu prompt to unmount drives. +# Provides you with mounted partitions, select one to unmount. +# Drives mounted at /, /boot and /home will not be options to unmount. + +unmountusb() { + [ -z "$drives" ] && exit + chosen="$(echo "$drives" | dmenu -i -p "Unmount which drive?")" || exit 1 + chosen="$(echo "$chosen" | awk '{print $1}')" + [ -z "$chosen" ] && exit + sudo -A umount "$chosen" && notify-send "💻 USB unmounting" "$chosen unmounted." + } + +unmountandroid() { \ + chosen="$(awk '/simple-mtpfs/ {print $2}' /etc/mtab | dmenu -i -p "Unmount which device?")" || exit 1 + [ -z "$chosen" ] && exit + sudo -A umount -l "$chosen" && notify-send "🤖 Android unmounting" "$chosen unmounted." + } + +asktype() { \ + choice="$(printf "USB\\nAndroid" | dmenu -i -p "Unmount a USB drive or Android device?")" || exit 1 + case "$choice" in + USB) unmountusb ;; + Android) unmountandroid ;; + esac + } + +drives=$(lsblk -nrpo "name,type,size,mountpoint" | awk '$4!~/\/boot|\/home$|SWAP/&&length($4)>1{printf "%s (%s)\n",$4,$3}') + +if ! grep simple-mtpfs /etc/mtab; then + [ -z "$drives" ] && echo "No drives to unmount." && exit + echo "Unmountable USB drive detected." + unmountusb +else + if [ -z "$drives" ] + then + echo "Unmountable Android device detected." + unmountandroid + else + echo "Unmountable USB drive(s) and Android device(s) detected." + asktype + fi +fi diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/pyrun b/home/.local/bin/scripts/gui/dmenu-scripts/pyrun new file mode 100755 index 0000000..aced1a5 --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/pyrun @@ -0,0 +1,8 @@ +#!/bin/sh + +# Simple wrapper to quickly execute a simple python command and have it printed out. +# The output is then sent back via notification. +# +# This already has random imported, since that's a common use-case for this script. + +echo "" | dmenu -i -p "Python" | xargs -0 -I % python -c "import random;print(%)" | xargs -I % notify-send "Pyrun output:" "%" diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/todo b/home/.local/bin/scripts/gui/dmenu-scripts/todo new file mode 100755 index 0000000..4cf8c90 --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/todo @@ -0,0 +1,36 @@ +#!/bin/sh +# This is inspired by dmenu's todo script made by suckless +# +# Manage TODO tasks in dmenu by writing them, remove by selecting +# an existing entry +# +# Configurable variables +# --------------------------------------------------------------------- + +FILE="${XDG_DATA_HOME:-$HOME/.local/share}/todos" +PROMPT="Add/delete a task: " + +# Logic +# --------------------------------------------------------------------- +mkdir -p "$(dirname $FILE)" +touch "$FILE" + +height=$(wc -l "$FILE" | awk '{print $1}') + +# Run dmenu and keep restarting it until it returns an empty output +cmd=$(dmenu -l "$height" -p "$PROMPT" "$@" < "$FILE") +while [ -n "$cmd" ]; do + # If the output matched an existing TODO, remove it + if grep -q "^$cmd\$" "$FILE"; then + grep -v "^$cmd\$" "$FILE" > "$FILE.$$" + mv "$FILE.$$" "$FILE" + height=$(( height - 1 )) + # If the output didn't match an existing TODO, it's a new one, add it + else + echo "$cmd" >> "$FILE" + height=$(( height + 1 )) + fi + + # Keep restarting until empty output + cmd=$(dmenu -l "$height" -p "$PROMPT" "$@" < "$FILE") +done diff --git a/home/.local/bin/scripts/gui/dmenu-scripts/website-link b/home/.local/bin/scripts/gui/dmenu-scripts/website-link new file mode 100755 index 0000000..c7a525f --- /dev/null +++ b/home/.local/bin/scripts/gui/dmenu-scripts/website-link @@ -0,0 +1,23 @@ +#!/usr/bin/env python +import feedparser +import subprocess + + +URL = "https://itsdrike.com/posts/index.xml" + + +def main(): + feed = feedparser.parse(URL) + titles = {entry['title']: entry['link'] for entry in feed['entries']} + + selected_page = subprocess.check_output( + ["dmenu", "-i", "-p", "Post"], + input="\n".join(titles.keys()), universal_newlines=True + ) + link = titles[selected_page.strip()] + + subprocess.check_output(["xsel", "-bi"], input=link, universal_newlines=True) + + +if __name__ == '__main__': + main() diff --git a/home/.local/bin/scripts/gui/gh-notification b/home/.local/bin/scripts/gui/gh-notification new file mode 100755 index 0000000..42be614 --- /dev/null +++ b/home/.local/bin/scripts/gui/gh-notification @@ -0,0 +1,299 @@ +#!/bin/sh + +# Parse arguments +# ------------------------------------------------------------------------------------ +ALL=0 +VERBOSE=0 +VERY_VERBOSE=0 +VERY_VERY_VERBOSE=0 +TEMP_SHOW=0 +DRY_RUN=0 +NO_CACHE=0 +NO_DISPLAY=0 +URGENCY="normal" +RESET=0 +while [ "$1" ]; do + case "$1" in + -h | --help) + cat << EOF +gh-notification is a tool that scrapes unread github notifications +It uses github-cli with meiji163/gh-notify addon to obtain the unread notifications +these are then parsed and sent as desktop notifications with notify-send + +Options: +-a | --all: Also process already read notifications +-t | --temp-files: Show names of used temporary files for each notification +-v | --verbose: Shows info about what's happening. +-vv | --very-verbose: Implies --verbose, shows some more info about what's happening +-vvv | --very-very-verbose: Implies --very-verbose and --temp-files, shows even more details, usually just for debugging +-d | --dry-run: Run without sending any notificatinos, when ran with -r, this will also prevent any actual cache file removals +-nc | --no-cache: Ignore the cache and send all found notifications, even if they were already sent before. +-nd | --no-display: When the script is ran from headless mode (such as by crontab), this will still attempt to set the DISPLAY and send the desktop notification +-r | --reset: Resets notification cache (storing which notifications were already sent), skips notification sending, WARNING: removes the whole cache, regardless of '--all') +-u | --urgency [urgency-level]: pass over notify-send urgency attribute (low, normal, critical) +EOF + exit 0 + ;; + -a | --all) + ALL=1 + ;; + -t | --temp-files) + TEMP_SHOW=1 + ;; + -v | --verbose) + VERBOSE=1 + ;; + -vv | --very-verbose) + VERBOSE=1 + VERY_VERBOSE=1 + ;; + -vvv | --very-very-verbose) + VERBOSE=1 + TEMP_SHOW=1 + VERY_VERBOSE=1 + VERY_VERY_VERBOSE=1 + ;; + -d | --dry-run) + DRY_RUN=1 + ;; + -nc | --no-cache) + NO_CACHE=1 + ;; + -nd | --no-display) + NO_DISPLAY=1 + ;; + -u | --urgency) + URGENCY="$2" + shift + ;; + -r | --reset) + RESET=1 + ;; + * ) + echo "Unknown argument '$1', use -h or --help for help" + exit 1 + ;; + esac + shift +done + + +# Perform cache resetting, if requested +# ------------------------------------------------------------------------------------ +if [ $RESET -eq 1 ]; then + if [ $NO_CACHE -eq 1 ]; then + echo "Can't ignore cache when resetting the cache..." + exit 1 + fi + out="$(find /tmp -maxdepth 1 -name 'gh-notification-*' 2>/dev/null)" + total="$(printf "%s\n" "$out" | wc -l)" + # Since we always end with a newline (to count the last entry as a line), we always get + # at least 1 as a total here, even if $out is empty. If we didn't use the \n, we'd always + # get 0, even if there was a single line, since it wasn't ended with a newline. To figure + # out whether there really is a line or not when we get a total of 1, we run character + # amount check as well + [ "$total" -eq 1 ] && [ "$(printf "%s" "$out" | wc -c)" -eq 0 ] && total=0 + + if [ $total -gt 0 ]; then + # Since the loop is running in a pipe, it can't modify variables, but we need to know + # which files have failed to be removed, so to get that information, we store it in a + # teporary file + fail_files_file="$(mktemp)" + + printf "%s\n" "$out" | while read -r file_name; do + # If desired, let user know about the found notification cache file + if [ $VERY_VERBOSE -eq 1 ] || [ $TEMP_SHOW -eq 1 ]; then + contents="$(cat "$file_name")" + title="$(printf "%s" "$contents" | awk -F '~@~' '{ print $1 }')" + + echo "Found cache tempfile: '$file_name' - $title" + if [ $VERY_VERY_VERBOSE -eq 1 ]; then + description="$(printf "%s" "$contents" | awk -F '~@~' '{ print $2 }')" + echo "Notification description: $description" + fi + fi + + if [ $DRY_RUN -ne 1 ]; then + # In case `rm` fails, keep track of which files it failed on + if ! rm "$file_name" 2>/dev/null; then + printf "%s\n" "$file_name" >> "$fail_files_file" + fi + else + [ $VERY_VERY_VERBOSE -eq 1 ] && echo "Tempfile removal skipped (dry-run)" + fi + + # Add a new-line separator on very very verbose to group prints from each iteration + [ $VERY_VERY_VERBOSE -eq 1 ] && echo "" + done + + # Recover failed files from the temporary file + failed_files="$(cat "$fail_files_file")" + failed="$(printf "%s" "$fail_files_file" | wc -l)" + rm "$fail_files_file" + + if [ $VERBOSE -eq 1 ]; then + echo "Notification cache was reset." + removed_count="$(("$total"-"$failed"))" + if [ $DRY_RUN -eq 1 ]; then + echo "Removed $removed_count files (dry-run: no files were actually removed)" + else + echo "Removed $removed_count files" + fi + fi + + # If some cache files were'nt removed successfully, inform the user about it + # regardless of verbosity, this shouldn't go silent, even though it may be fine + if [ "$failed" -gt 0 ]; then + echo "WARNING: Failed to remove $failed files." + echo "You probably don't have permission to remove these." + echo "Perhaps these were made by someone else? If so, you can ignore this warning." + if [ $VERBOSE -eq 0 ]; then + echo "Run with --verbose to show exactly which files weren't removed." + else + echo "These are:" + echo "$failed_files" + fi + fi + else + [ $VERBOSE -eq 1 ] && echo "No cache files found, nothing to reset" + fi + exit 0 +fi + + +# Helper functins +# ------------------------------------------------------------------------------------ +# This runs notify-send, and if NO_DISPLAY is set and we're running in headless +# mode, this will still try to send the notification by manually setting DISPLAY +# This also has a special handle that checks if dunst is the notification daemon +# in which case instead of using notify-send, we use dunstify to send the +# notification, with which we can also specify some more values. +send_notify() { + if [ $NO_DISPLAY -eq 1 ]; then + XDG_RUNTIME_DIR="/run/user/$(id -u)" \ + DISPLAY=:0 \ + notify-send --app-name=github-notification --urgency="$URGENCY" "$1" "$2" + else + notify-send --app-name=github-notification --urgency="$URGENCY" "$1" "$2" + fi +} + + +# Obtain notifications and show them, if they weren't showed (aren't in cache) already +# ------------------------------------------------------------------------------------ +# Request unread notifications with gh-notify extension for github-cli +[ "$ALL" -eq 1 ] && out="$(gh notify -s -a)" || out="$(gh notify -s)" +total="$(printf "%s\n" "$out" | wc -l)" +# Since we always end with a newline (to count the last entry as a line), we always get +# at least 1 as a total here, even if $out is empty. If we didn't use the \n, we'd always +# get 0, even if there was a single line, since it wasn't ended with a newline. To figure +# out whether there really is a line or not when we get a total of 1, we run character +# amount check as well +[ "$total" -eq 1 ] && [ "$(printf "%s" "$out" | wc -c)" -eq 0 ] && total=0 + +# Only run if we actually found some notifications +if [ "$total" -gt 0 ]; then + # Since the loop is running in a pipe, it can't modify variables, but we need to know + # how many notifications were sent, so to ge that information, we store it in a + # temporary file + sent_count_file="$(mktemp)" + printf "0" > "$sent_count_file" + + # Go through each notification, one by one + printf "%s\n" "$out" | while read -r line; do + # Parse out the data from given output lines + issue_type="$(echo "$line" | awk '{print $4}' | sed 's/\x1b\[[0-9;]*m//g')" + repo_id="$(echo "$line" | awk '{print $3}' | sed 's/\x1b\[[0-9;]*m//g')" + + + if [ "$issue_type" == "PullRequest" ]; then + issue_id="$(echo "$line" | awk '{print $5}' | sed 's/\x1b\[[0-9;]*m//g' | cut -c2-)" + description="$(echo "$line" | awk '{for (i=6; i "$temp_file" + hashsum="$(sum < "$temp_file" | cut -f 1 -d ' ')" + rm "$temp_file" + + tmpname="/tmp/gh-notification-$hashsum" + [ $TEMP_SHOW -eq 1 ] && echo "Tempfile: $tmpname" + + # If the temporary file is already present, this notification was already + # send and we don't want to re-send it + + # Only sent the notification if it wasn't already cached (doesn't have temp file) + # this avoids resending the same notifications + if [ ! -e "$tmpname" ] || [ $NO_CACHE -eq 1 ]; then + if [ $DRY_RUN -eq 1 ]; then + [ $VERY_VERBOSE -eq 1 ] && echo "Sending notification (dry-run, no actual notification was sent)" + else + [ $VERY_VERBOSE -eq 1 ] && echo "Sending notification" + send_notify "$name" "$description <$url>" + # Create the tempfile so that in the next run, we won't resend this notification again + # NOTE: We're storing the name and description into this file to make it easier + # to figure out what notification the tempfile belongs to, with ~@~ separator + printf "%s~@~%s" "$name" "$description" > "$tmpname" + fi + # Keep track of how many notifications were sent (didn't have a cache file) + sent="$(cat "$sent_count_file")" + sent="$(("$sent"+1))" + printf "%s" "$sent" > "$sent_count_file" + else + [ $VERY_VERBOSE -eq 1 ] && echo "Skipping (cached) - notification already sent" + fi + + # Add a new-line separator on very verbose to group prints from each iteration + [ $VERY_VERBOSE -eq 1 ] && echo "" + done + + # Recover amount of sent notifications from the temporary file + sent="$(cat "$sent_count_file")" + rm "$sent_count_file" + + if [ $VERBOSE -eq 1 ]; then + unsent="$(("$total"-"$sent"))" + if [ "$sent" -eq "$total" ]; then + echo "Found and sent $total new notifications" + elif [ "$unsent" -eq "$total" ]; then + echo "Found $total notifications, all of which were already sent (no new notifications to send)" + else + echo "Found $total notifications, of which $sent were new and sent ($unsent were skipped - cached/already sent)" + fi + fi +else + [ $VERBOSE -eq 1 ] && echo "No new notifications" +fi diff --git a/home/.local/bin/scripts/gui/setbg b/home/.local/bin/scripts/gui/setbg new file mode 100755 index 0000000..d1ce331 --- /dev/null +++ b/home/.local/bin/scripts/gui/setbg @@ -0,0 +1,35 @@ +#!/bin/sh + +# This script does the following: +# Run by itself, set the wallpaper +# If given a file, set that as the new wallpaper +# If given a directory, recursively choose a random file in it. + +# Location of the symlink to wallpaper image +bgloc="${XDG_DATA_HOME:-$HOME/.local/share}/background" + +trueloc="$(readlink -f "$1")" && +case "$(file --mime-type -b "$trueloc")" in + image/* ) + ln -sf "$(readlink -f "$1")" "$bgloc" + notify-send -i "$bgloc" "Changing wallpaper..." + ;; + inode/directory ) + randimg="$(find -L $trueloc -iregex '.*.\(jpg\|jpeg\|png\|gif\)' -type f | shuf -n 1)" + echo $randimg + ln -sf "$randimg" "$bgloc" + notify-send -i "$bgloc" "Random Wallpaper chosen." + ;; + *) + notify-send "Error" "Not a valid image." + exit 1 + ;; +esac + +# Use xwallpaper to set the background +if [ "$XDG_SESSION_TYPE" == "wayland" ]; then + killall swaybg 2>/dev/null + swaybg --image "$bgloc" & disown +else + xwallpaper --zoom "$bgloc" +fi diff --git a/home/.mozilla b/home/.mozilla new file mode 120000 index 0000000..2cf2199 --- /dev/null +++ b/home/.mozilla @@ -0,0 +1 @@ +.config/mozilla \ No newline at end of file diff --git a/home/.pki b/home/.pki new file mode 120000 index 0000000..2aacf8b --- /dev/null +++ b/home/.pki @@ -0,0 +1 @@ +.config/pki \ No newline at end of file diff --git a/home/.python_history b/home/.python_history new file mode 120000 index 0000000..e43cfa6 --- /dev/null +++ b/home/.python_history @@ -0,0 +1 @@ +.cache/python_history \ No newline at end of file diff --git a/root/.rsync-filter b/root/.rsync-filter new file mode 100644 index 0000000..a19ad20 --- /dev/null +++ b/root/.rsync-filter @@ -0,0 +1,22 @@ +# Filter file for rsync based backups +# rsync needs to be ran with --filter 'dir-merge /.rsync-filter' +# argument to look through this filter file +- /dev/* +- /proc/* +- /sys/* +- /media/* +- /mnt/* +- /tmp/* +- /run/* +- /var/run/* +- /var/lock/* +- /var/lib/docker/* +- /var/lib/schroot/* +- /lost+found +- /data/* +- /DATA/* +- /cdrom/* +- /sdcard/* +- /swapfile +- /swap/* +- /home/*/.cache/* diff --git a/root/etc/crypttab b/root/etc/crypttab new file mode 100644 index 0000000..d0f0493 --- /dev/null +++ b/root/etc/crypttab @@ -0,0 +1,13 @@ +# Configuration for encrypted block devices. +# See crypttab(5) for details. + +# NOTE: Do not list your root (/) partition here, it must be set up +# beforehand by the initramfs (/etc/mkinitcpio.conf). + +# +# home UUID=b8ad5c18-f445-495d-9095-c9ec4f9d2f37 /etc/mypassword1 +# data1 /dev/sda3 /etc/mypassword2 +# data2 /dev/sda5 /etc/cryptfs.key +# swap /dev/sdx4 /dev/urandom swap,cipher=aes-cbc-essiv:sha256,size=256 +# vol /dev/sdb7 none +cryptdata /dev/sda1 /luksKey diff --git a/root/etc/default/grub b/root/etc/default/grub new file mode 100644 index 0000000..e337efd --- /dev/null +++ b/root/etc/default/grub @@ -0,0 +1,73 @@ +# GRUB boot loader configuration + +GRUB_DEFAULT=0 +GRUB_TIMEOUT=5 +GRUB_DISTRIBUTOR="Arch" +GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet" + +# Since we're using encrypted root, during grub's configuration creation, it can +# only pick up on the UUID of the current (already encrypted) root, i.e. the mapper device. +# For that reason, we instead specify the UUID of our actual physical (encrypted) partition +# here ourselves. We then specify the name for the mapper device, and additional options. +# Specifically, we set allow-discards, which is here for SSD optimizations. +# +# Handling the decryption of this device will then be delegated to initramfs. Note that we do +# need to add the encrypt hook, along with some other hooks (like keyboard) to our mkinitcpio +# so that our initramfs will actually be able to prompt us for this password. +GRUB_CMDLINE_LINUX="cryptdevice=UUID=1864bad3-7e73-415a-a36d-49d941eb98c2:cryptroot:allow-discards" + +# Preload both GPT and MBR modules so that they are not missed +GRUB_PRELOAD_MODULES="part_gpt part_msdos" + +# Uncomment to enable booting from LUKS encrypted /boot partition +#GRUB_ENABLE_CRYPTODISK=y + +# Set to 'countdown' or 'hidden' to change timeout behavior, +# press ESC key to display menu. +GRUB_TIMEOUT_STYLE=menu + +# Uncomment to use basic console +GRUB_TERMINAL_INPUT=console + +# Uncomment to disable graphical terminal +#GRUB_TERMINAL_OUTPUT=console + +# The resolution used on graphical terminal +# note that you can use only modes which your graphic card supports via VBE +# you can see them in real GRUB with the command `vbeinfo' +GRUB_GFXMODE=auto + +# Uncomment to allow the kernel use the same resolution used by grub +GRUB_GFXPAYLOAD_LINUX=keep + +# Uncomment if you want GRUB to pass to the Linux kernel the old parameter +# format "root=/dev/xxx" instead of "root=/dev/disk/by-uuid/xxx" +#GRUB_DISABLE_LINUX_UUID=true + +# Uncomment to disable generation of recovery mode menu entries +GRUB_DISABLE_RECOVERY=true + +# Uncomment and set to the desired menu colors. Used by normal and wallpaper +# modes only. Entries specified as foreground/background. +#GRUB_COLOR_NORMAL="light-blue/black" +#GRUB_COLOR_HIGHLIGHT="light-cyan/blue" + +# Uncomment one of them for the gfx desired, a image background or a gfxtheme +#GRUB_BACKGROUND="/path/to/wallpaper" +#GRUB_THEME="/path/to/gfxtheme" + +# Uncomment to get a beep at GRUB start +#GRUB_INIT_TUNE="480 440 1" + +# Uncomment to make GRUB remember the last selection. This requires +# setting 'GRUB_DEFAULT=saved' above. +#GRUB_SAVEDEFAULT=true + +# Uncomment to disable submenus in boot menu +#GRUB_DISABLE_SUBMENU=y + +# Probing for other operating systems is disabled for security reasons. Read +# documentation on GRUB_DISABLE_OS_PROBER, if still want to enable this +# functionality install os-prober and uncomment to detect and include other +# operating systems. +#GRUB_DISABLE_OS_PROBER=false diff --git a/root/etc/modprobe.d/blacklist-noveau.conf b/root/etc/modprobe.d/blacklist-noveau.conf new file mode 100644 index 0000000..67c5630 --- /dev/null +++ b/root/etc/modprobe.d/blacklist-noveau.conf @@ -0,0 +1,2 @@ +blacklist noveau +options noveau modeset=0 diff --git a/root/etc/modprobe.d/nobeep.conf b/root/etc/modprobe.d/nobeep.conf new file mode 100644 index 0000000..b46792e --- /dev/null +++ b/root/etc/modprobe.d/nobeep.conf @@ -0,0 +1 @@ +blacklist pcspkr diff --git a/root/etc/pacman.conf b/root/etc/pacman.conf new file mode 100644 index 0000000..59b1836 --- /dev/null +++ b/root/etc/pacman.conf @@ -0,0 +1,105 @@ +# +# /etc/pacman.conf +# +# See the pacman.conf(5) manpage for option and repository directives + +# +# GENERAL OPTIONS +# +[options] +# The following paths are commented out with their default values listed. +# If you wish to use different paths, uncomment and update the paths. +#RootDir = / +#DBPath = /var/lib/pacman/ +#CacheDir = /var/cache/pacman/pkg/ +#LogFile = /var/log/pacman.log +#GPGDir = /etc/pacman.d/gnupg/ +#HookDir = /etc/pacman.d/hooks/ +HoldPkg = pacman glibc +#XferCommand = /usr/bin/curl -L -C - -f -o %o %u +#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u +#CleanMethod = KeepInstalled +Architecture = auto + +# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup +#IgnorePkg = +#IgnoreGroup = + +#NoUpgrade = +#NoExtract = + +# Misc options +#UseSyslog +Color +CheckSpace +VerbosePkgLists +#DisableDownloadTimeout +#ILoveCandy +ParallelDownloads = 8 + +# By default, pacman accepts packages signed by keys that its local keyring +# trusts (see pacman-key and its man page), as well as unsigned packages. +SigLevel = Required DatabaseOptional +LocalFileSigLevel = Optional +#RemoteFileSigLevel = Required + +# NOTE: You must run `pacman-key --init` before first using pacman; the local +# keyring can then be populated with the keys of all official Arch Linux +# packagers with `pacman-key --populate archlinux`. + +# +# REPOSITORIES +# - can be defined here or included from another file +# - pacman will search repositories in the order defined here +# - local/custom mirrors can be added here or in separate files +# - repositories listed first will take precedence when packages +# have identical names, regardless of version number +# - URLs will have $repo replaced by the name of the current repo +# - URLs will have $arch replaced by the name of the architecture +# +# Repository entries are of the format: +# [repo-name] +# Server = ServerName +# Include = IncludePath +# +# The header [repo-name] is crucial - it must be present and +# uncommented to enable the repo. +# + +# The testing repositories are disabled by default. To enable, uncomment the +# repo name header and Include lines. You can add preferred servers immediately +# after the header, and they will be used before the default mirrors. + +# Use blackarch first, so that other indices can take precedence in +# versions, usually core/extra/community/multilib have newer versions +# in comparison to blackarch index +#[testing] +#Include = /etc/pacman.d/mirrorlist + +[core] +Include = /etc/pacman.d/mirrorlist + +[extra] +Include = /etc/pacman.d/mirrorlist + +#[community-testing] +#Include = /etc/pacman.d/mirrorlist + +[community] +Include = /etc/pacman.d/mirrorlist + +# If you want to run 32 bit applications on your x86_64 system, +# enable the multilib repositories as required here. + +#[multilib-testing] +#Include = /etc/pacman.d/mirrorlist + +[multilib] +Include = /etc/pacman.d/mirrorlist + +# An example of a custom package repository. See the pacman manpage for +# tips on creating your own repositories. +#[custom] +#SigLevel = Optional TrustAll +#Server = file:///home/custompkgs + diff --git a/root/etc/pipewire/pipewire-pulse.conf b/root/etc/pipewire/pipewire-pulse.conf new file mode 100644 index 0000000..2e9bb0d --- /dev/null +++ b/root/etc/pipewire/pipewire-pulse.conf @@ -0,0 +1,11 @@ +pulse.rules = [ + { + # Discord notification sounds fix + matches = [ { application.process.binary = "Discord" } ] + actions = { + update-props = { + pulse.min.quantum = 1024/48000 # 21ms + } + } + } +} diff --git a/root/etc/sudoers b/root/etc/sudoers new file mode 100644 index 0000000..e04b581 --- /dev/null +++ b/root/etc/sudoers @@ -0,0 +1,99 @@ +## sudoers file. +## +## This file MUST be edited with the 'visudo' command as root. +## Failure to use 'visudo' may result in syntax or file permission errors +## that prevent sudo from running. +## +## See the sudoers man page for the details on how to write a sudoers file. +## + +## +## Host alias specification +## +## Groups of machines. These may include host names (optionally with wildcards), +## IP addresses, network numbers or netgroups. +# Host_Alias WEBSERVERS = www1, www2, www3 + +## +## User alias specification +## +## Groups of users. These may consist of user names, uids, Unix groups, +## or netgroups. +# User_Alias ADMINS = millert, dowdy, mikef + +## +## Cmnd alias specification +## +## Groups of commands. Often used to group related commands together. +# Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice, \ +# /usr/bin/pkill, /usr/bin/top +# Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff + +## +## Defaults specification +## +## You may wish to keep some of the following environment variables +## when running commands via sudo. +## +## Locale settings +# Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET" +## +## Run X applications through sudo; HOME is used to find the +## .Xauthority file. Note that other programs use HOME to find +## configuration files and this may lead to privilege escalation! +# Defaults env_keep += "HOME" +## +## X11 resource path settings +# Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH" +## +## Desktop path settings +# Defaults env_keep += "QTDIR KDEDIR" +## +## Allow sudo-run commands to inherit the callers' ConsoleKit session +# Defaults env_keep += "XDG_SESSION_COOKIE" +## +## Uncomment to enable special input methods. Care should be taken as +## this may allow users to subvert the command being run via sudo. +# Defaults env_keep += "XMODIFIERS GTK_IM_MODULE QT_IM_MODULE QT_IM_SWITCHER" +## +## Uncomment to use a hard-coded PATH instead of the user's to find commands +# Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +## +## Uncomment to send mail if the user does not enter the correct password. +# Defaults mail_badpass +## +## Uncomment to enable logging of a command's output, except for +## sudoreplay and reboot. Use sudoreplay to play back logged sessions. +Defaults log_output +Defaults!/usr/bin/sudoreplay !log_output +Defaults!/usr/local/bin/sudoreplay !log_output +Defaults!REBOOT !log_output + +# Add some fine insults +Defaults insults + +## +## Runas alias specification +## + +## +## User privilege specification +## +root ALL=(ALL) ALL + +## Uncomment to allow members of group wheel to execute any command +%wheel ALL=(ALL) ALL + +## Same thing without a password +# %wheel ALL=(ALL) NOPASSWD: ALL + +## Uncomment to allow members of group sudo to execute any command +# %sudo ALL=(ALL) ALL + +## Uncomment to allow any user to run sudo if they know the password +## of the user they are running the command as (root by default). +# Defaults targetpw # Ask for the password of the target user +# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw' + +## Read drop-in files from /etc/sudoers.d +@includedir /etc/sudoers.d diff --git a/root/etc/sudoers.d/brightness-mod b/root/etc/sudoers.d/brightness-mod new file mode 100644 index 0000000..75dd592 --- /dev/null +++ b/root/etc/sudoers.d/brightness-mod @@ -0,0 +1,2 @@ +ALL ALL=(ALL) NOPASSWD: /usr/bin/tee /sys/class/backlight/intel_backlight/brightness + diff --git a/root/etc/sudoers.d/poweroff b/root/etc/sudoers.d/poweroff new file mode 100644 index 0000000..73ae525 --- /dev/null +++ b/root/etc/sudoers.d/poweroff @@ -0,0 +1,4 @@ +ALL ALL=(ALL) NOPASSWD: /sbin/poweroff +ALL ALL=(ALL) NOPASSWD: /sbin/shutdown +ALL ALL=(ALL) NOPASSWD: /sbin/reboot + diff --git a/root/etc/systemd/system/paccache.timer b/root/etc/systemd/system/paccache.timer new file mode 100644 index 0000000..6528cb7 --- /dev/null +++ b/root/etc/systemd/system/paccache.timer @@ -0,0 +1,14 @@ +# Clean pacman cache of old and uninstalled packages every month +# This needs to be started by running `systemctl start paccache.timer` +# Usage requires `pacman-contrib` package to be installed + +[Unit] +Description=Clean-up old pacman pkg + +[Timer] +OnCalendar=weekly +AccuracySec=1h +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/root/usr/local/src/Hyprland b/root/usr/local/src/Hyprland new file mode 160000 index 0000000..d994ad7 --- /dev/null +++ b/root/usr/local/src/Hyprland @@ -0,0 +1 @@ +Subproject commit d994ad75e80df6c97c400f85e0fbdf11dbb5ca49 diff --git a/root/usr/local/src/eww b/root/usr/local/src/eww new file mode 160000 index 0000000..7a0e1b7 --- /dev/null +++ b/root/usr/local/src/eww @@ -0,0 +1 @@ +Subproject commit 7a0e1b77f24ee89d627e552f9abc55eb636aaaa6 diff --git a/root/usr/local/src/z.lua b/root/usr/local/src/z.lua new file mode 160000 index 0000000..0992ebf --- /dev/null +++ b/root/usr/local/src/z.lua @@ -0,0 +1 @@ +Subproject commit 0992ebf9f1f6cdaa114e65d3aa76bfb1bd9a6fd4 diff --git a/root/usr/share/zsh/site-functions/zsh-autosuggestions b/root/usr/share/zsh/site-functions/zsh-autosuggestions new file mode 160000 index 0000000..a411ef3 --- /dev/null +++ b/root/usr/share/zsh/site-functions/zsh-autosuggestions @@ -0,0 +1 @@ +Subproject commit a411ef3e0992d4839f0732ebeb9823024afaaaa8 diff --git a/root/usr/share/zsh/site-functions/zsh-syntax-highlighting b/root/usr/share/zsh/site-functions/zsh-syntax-highlighting new file mode 160000 index 0000000..122dc46 --- /dev/null +++ b/root/usr/share/zsh/site-functions/zsh-syntax-highlighting @@ -0,0 +1 @@ +Subproject commit 122dc464392302114556b53ec01a1390c54f739f diff --git a/root/usr/share/zsh/site-functions/zsh-you-should-use b/root/usr/share/zsh/site-functions/zsh-you-should-use new file mode 160000 index 0000000..13c8635 --- /dev/null +++ b/root/usr/share/zsh/site-functions/zsh-you-should-use @@ -0,0 +1 @@ +Subproject commit 13c86356553b80e0e0cbf1ecf6d82cfa79751b5a diff --git a/sync.py b/sync.py new file mode 100755 index 0000000..ad5e83a --- /dev/null +++ b/sync.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +from __future__ import annotations + +import hashlib +import sys +from collections.abc import Iterable, Iterator +from enum import Enum, auto +from pathlib import Path +from typing import NamedTuple + +try: + import rich +except ImportError: + print("rich not found (`pip install rich`), falling back to no colors", file=sys.stderr) + rich = None + +DOTHOMEDIR = Path("./home") +HOMEDIR = Path("~") +DOTROOTDIR = Path("./root") +ROOTDIR = Path("/") + + +class DiffStatus(Enum): + NOT_FOUND = auto() + PERMISSION_ERROR = auto() + MATCH = auto() + EXPECTED_SYMLINK = auto() + UNEXPECTED_SYMLINK = auto() + CONTENT_DIFFERS = auto() + SYMLINK_DIFFERS = auto() + + +class FileDiff(NamedTuple): + dot_file: Path + sys_file: Path + status: DiffStatus + + def __repr__(self) -> str: + dot_file = str(self.rel_dot_file) + sys_file = str(self.sys_file) + status = self.status.name + return f"FileDiff({dot_file=}, {sys_file=}, {status=})" + + @property + def rel_dot_file(self) -> Path: + """Returns path to a dot_file relative to workdir.""" + return self.dot_file.relative_to(Path.cwd()) + + +def iter_dir(directory: Path) -> Iterator[Path]: + """Recursively iterate over given directory and yield all files in it.""" + for subpath in directory.iterdir(): + if subpath.is_file() or subpath.is_symlink(): + yield subpath + else: + yield from iter_dir(subpath) + + +def file_sum(file: Path) -> str: + """Compute SHA-256 hash sum of given file.""" + sha256_hash = hashlib.sha256() + with file.open("rb") as f: + for byte_block in iter(lambda: f.read(4096), b""): + sha256_hash.update(byte_block) + return sha256_hash.hexdigest() + + +def compare_files(dot_file: Path, sys_file: Path) -> DiffStatus: + """Compare two files returning their diff status.""" + try: + if not sys_file.exists(): + return DiffStatus.NOT_FOUND + except PermissionError: + return DiffStatus.PERMISSION_ERROR + + if dot_file.is_symlink(): + if sys_file.is_symlink(): + if dot_file.readlink() == sys_file.readlink(): + return DiffStatus.MATCH + else: + # In case the sys_file link uses an absolute path, make sure + # it points to the same location, even if that location is a + # symlink. + dot_target = sys_file.parent.joinpath(dot_file.readlink()).absolute() + sys_target = sys_file.parent.joinpath(sys_file.readlink()).absolute() + if dot_target == sys_target: + return DiffStatus.MATCH + return DiffStatus.SYMLINK_DIFFERS + return DiffStatus.EXPECTED_SYMLINK + elif sys_file.is_symlink(): + return DiffStatus.UNEXPECTED_SYMLINK + + try: + if file_sum(dot_file) == file_sum(sys_file): + return DiffStatus.MATCH + except PermissionError: + return DiffStatus.PERMISSION_ERROR + + return DiffStatus.CONTENT_DIFFERS + + +def iter_pairs() -> Iterator[tuple[Path, Path]]: + """Go through all files in the dotfiles directories and match them to system paths. + + Yields tuples of (dotfile file path, matching system path) + """ + for dot_file in iter_dir(DOTHOMEDIR): + real_file = Path(HOMEDIR, *dot_file.parts[1:]) + yield dot_file.expanduser().absolute(), real_file.expanduser().absolute() + + for dot_file in iter_dir(DOTROOTDIR): + real_file = Path(ROOTDIR, *dot_file.parts[1:]) + yield dot_file.expanduser().absolute(), real_file.expanduser().absolute() + + +def iter_diffs() -> Iterator[FileDiff]: + """Go through all files and compute their diffs.""" + for dot_file, sys_file in iter_pairs(): + diff_status = compare_files(dot_file, sys_file) + yield FileDiff(dot_file, sys_file, diff_status) + + +def print_status(diffs: Iterable[FileDiff]) -> None: + """Pretty print the individual diff statuses.""" + # Exhause the iterable, and ensure we work on a copy + diffs = list(diffs) + + # Sort by DiffStatus, with MATCH entries being first + diffs.sort(key=lambda v: (v.status is not DiffStatus.MATCH, v.status.name)) + + if rich is None: + for diff in diffs: + print(f"{diff.status.name} -> {diff.sys_file}") + return + + from rich.table import Table + table = Table() + table.add_column("Status") + table.add_column("System file", style="magenta") + table.add_column("Dotfile file", style="magenta") + + for diff in diffs: + _str_status = diff.status.name.replace("_", " ") + if diff.status is DiffStatus.MATCH: + status_str = (f"[green]{_str_status}[/green]") + elif diff.status is DiffStatus.PERMISSION_ERROR: + status_str = f"[bold yellow]{_str_status}[/bold yellow]" + elif diff.status is DiffStatus.NOT_FOUND: + status_str = f"[bold orange_red1]{_str_status}[/bold orange_red1]" + else: + status_str = f"[bold red]{_str_status}[/bold red]" + + try: + # Unexpand home (/home/xyz/foo -> ~/foo) + sys_file = Path("~") / diff.sys_file.relative_to(Path.home()) + except ValueError: # File not in home + sys_file = diff.sys_file + + sys_file = str(sys_file) + dot_file = "./" + str(diff.rel_dot_file) + table.add_row(status_str, sys_file, dot_file) + + rich.print(table) + + +def exclude_fun(diff: FileDiff) -> bool: + EXCLUDE_RULES = [ + lambda d: d.status is DiffStatus.MATCH, + lambda d: d.dot_file.name == ".keep" and d.sys_file.parent.is_dir(), + lambda d: Path("root/etc/opensnitchd/rules") in d.rel_dot_file.parents, + lambda d: Path("home/.config/xmobar") in d.rel_dot_file.parents, + lambda d: Path("home/.config/xmonad") in d.rel_dot_file.parents, + lambda d: Path("home/.local/share/xmonad") in d.rel_dot_file.parents, + lambda d: Path("home/.config/topgrade.toml") == d.rel_dot_file, + lambda d: Path("home/.config/newsboat") in d.rel_dot_file.parents, + lambda d: Path("home/.cache/zsh/history") == d.rel_dot_file and d.status is DiffStatus.CONTENT_DIFFERS, + lambda d: Path("home/.local/scripts") in d.rel_dot_file.parents, # Temporary + lambda d: Path("root") in d.rel_dot_file.parents, # Temporary + ] + + for exc_rule in EXCLUDE_RULES: + if exc_rule(diff): + return False + return True + + +def main() -> None: + diffs = iter_diffs() + diffs = filter(exclude_fun, diffs) + print_status(diffs) + + + +if __name__ == "__main__": + main()