From 24b050dab1fb6401a17f051995613b70b5f30f99 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 16:50:42 -0500 Subject: [PATCH 001/326] Initial commit --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE 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 +. From 64545a57f94095286367bc74d0f0a0c9b531f004 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 16:57:48 -0500 Subject: [PATCH 002/326] Pull in dotbot --- .gitmodules | 3 +++ dotbot | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 dotbot diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1ce5c11 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dotbot"] + path = dotbot + url = https://github.com/anishathalye/dotbot diff --git a/dotbot b/dotbot new file mode 160000 index 0000000..769767c --- /dev/null +++ b/dotbot @@ -0,0 +1 @@ +Subproject commit 769767c129c8f26eb66dca06dfa4a1bddbac8a9e From 32eaaae4b2c77902026b085ee088fb38bce11faf Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 16:57:52 -0500 Subject: [PATCH 003/326] set up repo --- .gitmodules | 1 + install | 15 +++++++++++++++ install.conf.yaml | 0 3 files changed, 16 insertions(+) create mode 100755 install create mode 100644 install.conf.yaml diff --git a/.gitmodules b/.gitmodules index 1ce5c11..1af14d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "dotbot"] path = dotbot url = https://github.com/anishathalye/dotbot + ignore = dirty diff --git a/install b/install new file mode 100755 index 0000000..5a7e72c --- /dev/null +++ b/install @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e + +CONFIG="install.conf.yaml" +DOTBOT_DIR="dotbot" + +DOTBOT_BIN="bin/dotbot" +BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +cd "${BASEDIR}" +git -C "${DOTBOT_DIR}" submodule sync --quiet --recursive +git submodule update --init --recursive "${DOTBOT_DIR}" + +"${BASEDIR}/${DOTBOT_DIR}/${DOTBOT_BIN}" -d "${BASEDIR}" -c "${CONFIG}" "${@}" diff --git a/install.conf.yaml b/install.conf.yaml new file mode 100644 index 0000000..e69de29 From ef7a765132173eaf9b7d9a6ea02fb68fe1744e32 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 17:02:20 -0500 Subject: [PATCH 004/326] Basic configuration --- configs/git/.gitconfig | 10 ++++++ configs/ssh/config | 70 ++++++++++++++++++++++++++++++++++++++++++ install.conf.yaml | 16 ++++++++++ 3 files changed, 96 insertions(+) create mode 100644 configs/git/.gitconfig create mode 100644 configs/ssh/config diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig new file mode 100644 index 0000000..980d51d --- /dev/null +++ b/configs/git/.gitconfig @@ -0,0 +1,10 @@ +[user] + email = ewpratten@gmail.com + name = Evan Pratten +[filter "lfs"] + clean = git-lfs clean -- %f + smudge = git-lfs smudge -- %f + process = git-lfs filter-process + required = true +[url "ssh://git@github.com/"] + insteadOf = https://github.com/ diff --git a/configs/ssh/config b/configs/ssh/config new file mode 100644 index 0000000..bc600ad --- /dev/null +++ b/configs/ssh/config @@ -0,0 +1,70 @@ + +# Personal servers +Host rtl-netlink + HostName netlink.local + User pi + +Host rtl-compute + Hostname compute.local + User pi + +Host gw-ca-tor-01 + Hostname gw-ca-tor-01.servers.retrylife.ca + +Host hp-desktop + Hostname 10.9.0.12 + +# Github SSH adapter for restricted networks +Host github.com + HostName ssh.github.com + Port 443 + +Host gist.github.com + HostName ssh.github.com + Port 443 + +# IndustrialBrothers Internal network +Host ib-* + Hostname %h.industrialbrothers.com + IdentityFile ~/.ssh/industrialbrothers_id_ed25519 + RequestTTY force + User epratten + +Host *.industrialbrothers.com + IdentityFile ~/.ssh/industrialbrothers_id_ed25519 + +Host ib-8700k-125 + RemoteCommand powershell "& 'C:\Program Files\Git\bin\sh.exe' --login" +Host ib-8700k-139 + RemoteCommand powershell "& 'C:\Program Files\Git\bin\sh.exe' --login" + +Host ib-rfcpu-002-lnx + User evan + +Host ib-rfcpu-001-lnx + User epratten + +# Default hostnames I may encounter in the wild +Host openrepeater.local + HostName openrepeater.local + User root + StrictHostKeyChecking no + +Host raspberrypi.local + StrictHostKeyChecking no + User pi + +# Raider Robotics +Host 10.50.24.2 + StrictHostKeyChecking no + User admin + +# Sheridan +Host atlas + User prattene + RequestTTY yes + RemoteCommand ~/.local/bin/zsh --login + +Host sheridan-cpanel + User prattene + HostName cpanel.prattene.dev.fast.sheridanc.on.ca diff --git a/install.conf.yaml b/install.conf.yaml index e69de29..c1e81e7 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -0,0 +1,16 @@ +- defaults: + link: + relink: true + +- clean: ['~'] + +- link: + ~/.gitconfig: configs/git/.gitconfig + ~/.ssh/config: configs/ssh/config + +- create: + - ~/Downloads + - ~/bin + +- shell: + - [git submodule update --init --recursive, Installing submodules] \ No newline at end of file From f927d183cd25a730d66e49ba35c00d8959664395 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 17:05:19 -0500 Subject: [PATCH 005/326] change ssh settings --- configs/ssh/{config => config_} | 0 install.conf.yaml | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) rename configs/ssh/{config => config_} (100%) diff --git a/configs/ssh/config b/configs/ssh/config_ similarity index 100% rename from configs/ssh/config rename to configs/ssh/config_ diff --git a/install.conf.yaml b/install.conf.yaml index c1e81e7..3ecea76 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -6,7 +6,9 @@ - link: ~/.gitconfig: configs/git/.gitconfig - ~/.ssh/config: configs/ssh/config + ~/.ssh/config: + path: configs/ssh/config + force: true - create: - ~/Downloads From 26bc5c35e3b422ce499ad94f82ac1ffee0d5e3ab Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 17:05:30 -0500 Subject: [PATCH 006/326] bring back config file --- configs/ssh/{config_ => config} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename configs/ssh/{config_ => config} (100%) diff --git a/configs/ssh/config_ b/configs/ssh/config similarity index 100% rename from configs/ssh/config_ rename to configs/ssh/config From 2567417d14739bd3763f81a8f86ca970b67c162c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 17:19:37 -0500 Subject: [PATCH 007/326] Set up zsh stuff --- configs/zsh/.zshrc | 17 ++++++++++ configs/zsh/by_host/ewpratten-desktop.sh | 1 + configs/zsh/by_host/ewpratten-laptop.sh | 1 + configs/zsh/macros.sh | 40 ++++++++++++++++++++++++ configs/zsh/prompt.sh | 24 ++++++++++++++ install.conf.yaml | 3 -- 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 configs/zsh/.zshrc create mode 100644 configs/zsh/by_host/ewpratten-desktop.sh create mode 100644 configs/zsh/by_host/ewpratten-laptop.sh create mode 100644 configs/zsh/macros.sh create mode 100644 configs/zsh/prompt.sh diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc new file mode 100644 index 0000000..1298565 --- /dev/null +++ b/configs/zsh/.zshrc @@ -0,0 +1,17 @@ + +# There are some important env vars that need to exist +export ZSH="$HOME/.oh-my-zsh" +export EWCONFIG_ROOT="$HOME/.config/ewconfig" + +# Load zsh-specific stuff +plugins=(zsh-autosuggestions) +source $ZSH/oh-my-zsh.sh + +# Load my custom prompt and macros +. $EWCONFIG_ROOT/configs/zsh/prompt.sh +. $EWCONFIG_ROOT/configs/zsh/macros.sh + +# Load per-host configuration +if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then + . $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh +fi \ No newline at end of file diff --git a/configs/zsh/by_host/ewpratten-desktop.sh b/configs/zsh/by_host/ewpratten-desktop.sh new file mode 100644 index 0000000..efcbaec --- /dev/null +++ b/configs/zsh/by_host/ewpratten-desktop.sh @@ -0,0 +1 @@ +#! /bin/bash \ No newline at end of file diff --git a/configs/zsh/by_host/ewpratten-laptop.sh b/configs/zsh/by_host/ewpratten-laptop.sh new file mode 100644 index 0000000..efcbaec --- /dev/null +++ b/configs/zsh/by_host/ewpratten-laptop.sh @@ -0,0 +1 @@ +#! /bin/bash \ No newline at end of file diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh new file mode 100644 index 0000000..dae2241 --- /dev/null +++ b/configs/zsh/macros.sh @@ -0,0 +1,40 @@ +alias ls="ls --color=auto" +alias ll="ls -l" +alias la="ls -a" +alias :q="exit" +alias :wq="exit" +alias cls=clear +alias p4='ping 8.8.8.8 -c 4' +alias quickhttp='sudo python -m SimpleHTTPServer 443' +alias zshreload="source ~/.zshrc" + +# Makes a directory, then moves into it +mkcd() { + if [ $# != 1 ]; then + echo "Usage: mkcd " + else + mkdir -p $1 && cd $1 + fi +} + +# Auto-extract anything +extract() { + if [ -f $1 ]; then + case $1 in + *.tar.bz2) tar xvjf $1 ;; + *.tar.gz) tar xvzf $1 ;; + *.bz2) bunzip2 $1 ;; + *.rar) unrar x $1 ;; + *.gz) gunzip $1 ;; + *.tar) tar xvf $1 ;; + *.tbz2) tar xvjf $1 ;; + *.tgz) tar xvzf $1 ;; + *.zip) unzip $1 ;; + *.Z) uncompress $1 ;; + *.7z) 7z x $1 ;; + *) echo "don't know how to extract '$1'..." ;; + esac + else + echo "'$1' is not a valid file!" + fi +} \ No newline at end of file diff --git a/configs/zsh/prompt.sh b/configs/zsh/prompt.sh new file mode 100644 index 0000000..9ef1dee --- /dev/null +++ b/configs/zsh/prompt.sh @@ -0,0 +1,24 @@ +# This is some kind of dark magic. +# I have no memory of whats going on here, but this has been my config since 2015-ish, so it shall not be touched. + +autoload -U colors && colors +NEWLINE=$'\n' +export PROMPT="%{$fg[green]%}%n@%M %{$fg[cyan]%}%~ $ %{$reset_color%}" +setopt prompt_subst +autoload -Uz vcs_info +zstyle ':vcs_info:*' actionformats \ + '%F{5}(%f%s%F{5})%F{3}-%F{5}[%F{2}%b%F{3}|%F{1}%a%F{5}]%f ' +zstyle ':vcs_info:*' formats \ + '%F{5}(%f%s%F{5})%F{3}-%F{5}[%F{2}%b%F{5}]%f ' +zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat '%b%F{1}:%F{3}%r' + +zstyle ':vcs_info:*' enable git cvs svn + +# or use pre_cmd, see man zshcontrib +vcs_info_wrapper() { + vcs_info + if [ -n "$vcs_info_msg_0_" ]; then + echo "%{$fg[grey]%}${vcs_info_msg_0_}%{$reset_color%}$del" + fi +} +export RPROMPT=$'%@ $(vcs_info_wrapper) %?' diff --git a/install.conf.yaml b/install.conf.yaml index 3ecea76..8d56d42 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -6,9 +6,6 @@ - link: ~/.gitconfig: configs/git/.gitconfig - ~/.ssh/config: - path: configs/ssh/config - force: true - create: - ~/Downloads From 4f191519e6dc883159146746af5ad0aa1624830c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 17:19:57 -0500 Subject: [PATCH 008/326] Actually create zshrc --- install.conf.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/install.conf.yaml b/install.conf.yaml index 8d56d42..6d2c922 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -6,6 +6,7 @@ - link: ~/.gitconfig: configs/git/.gitconfig + ~/.zshrc: configs/zsh/.zshrc - create: - ~/Downloads From dd526c965c61d88a9c9f873abb9f7347cb2af755 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 17:22:32 -0500 Subject: [PATCH 009/326] force zsh --- install.conf.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.conf.yaml b/install.conf.yaml index 6d2c922..1ed7a4d 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -6,7 +6,9 @@ - link: ~/.gitconfig: configs/git/.gitconfig - ~/.zshrc: configs/zsh/.zshrc + ~/.zshrc: + path: configs/zsh/.zshrc + force: true - create: - ~/Downloads From 92b6cbad4b14a8376437af3a986822c9fd03598d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 17:25:21 -0500 Subject: [PATCH 010/326] no longer depend on omz --- configs/zsh/.zshrc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 1298565..98f992f 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -1,12 +1,7 @@ # There are some important env vars that need to exist -export ZSH="$HOME/.oh-my-zsh" export EWCONFIG_ROOT="$HOME/.config/ewconfig" -# Load zsh-specific stuff -plugins=(zsh-autosuggestions) -source $ZSH/oh-my-zsh.sh - # Load my custom prompt and macros . $EWCONFIG_ROOT/configs/zsh/prompt.sh . $EWCONFIG_ROOT/configs/zsh/macros.sh From c5e8f95ea1e81ddaac1898b36085a5ee17df0c71 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 18:10:15 -0500 Subject: [PATCH 011/326] tabset --- configs/tabset/devices/huion-kamvas-13/name | 1 + .../tabset/devices/huion-kamvas-13/peripherals | 2 ++ .../huion-kamvas-13/profiles/blender.sh | 18 ++++++++++++++++++ .../huion-kamvas-13/profiles/default.sh | 1 + .../huion-kamvas-13/profiles/disabled.sh | 18 ++++++++++++++++++ .../devices/huion-kamvas-13/profiles/gimp.sh | 18 ++++++++++++++++++ configs/zsh/prompt.sh | 1 + install.conf.yaml | 2 ++ 8 files changed, 61 insertions(+) create mode 100755 configs/tabset/devices/huion-kamvas-13/name create mode 100755 configs/tabset/devices/huion-kamvas-13/peripherals create mode 100755 configs/tabset/devices/huion-kamvas-13/profiles/blender.sh create mode 120000 configs/tabset/devices/huion-kamvas-13/profiles/default.sh create mode 100755 configs/tabset/devices/huion-kamvas-13/profiles/disabled.sh create mode 100755 configs/tabset/devices/huion-kamvas-13/profiles/gimp.sh diff --git a/configs/tabset/devices/huion-kamvas-13/name b/configs/tabset/devices/huion-kamvas-13/name new file mode 100755 index 0000000..3ed584f --- /dev/null +++ b/configs/tabset/devices/huion-kamvas-13/name @@ -0,0 +1 @@ +Huion Kamvas 13 \ No newline at end of file diff --git a/configs/tabset/devices/huion-kamvas-13/peripherals b/configs/tabset/devices/huion-kamvas-13/peripherals new file mode 100755 index 0000000..ea78a73 --- /dev/null +++ b/configs/tabset/devices/huion-kamvas-13/peripherals @@ -0,0 +1,2 @@ +Tablet Monitor stylus +Tablet Monitor Pad pad \ No newline at end of file diff --git a/configs/tabset/devices/huion-kamvas-13/profiles/blender.sh b/configs/tabset/devices/huion-kamvas-13/profiles/blender.sh new file mode 100755 index 0000000..2d54072 --- /dev/null +++ b/configs/tabset/devices/huion-kamvas-13/profiles/blender.sh @@ -0,0 +1,18 @@ +# Top three buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 1 "key +ctrl +z -z -ctrl" +xsetwacom --set "Tablet Monitor Pad pad" Button 2 "key +ctrl +tab -tab -ctrl" +xsetwacom --set "Tablet Monitor Pad pad" Button 3 "key x" + +# Middle two buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 8 "key shift" +xsetwacom --set "Tablet Monitor Pad pad" Button 9 "key ctrl" + +# Bottom three buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 10 "key 1" +xsetwacom --set "Tablet Monitor Pad pad" Button 11 "key 3" +xsetwacom --set "Tablet Monitor Pad pad" Button 12 "key 0" + +# Pen buttons +xsetwacom set "Tablet Monitor stylus" "Button" "1" "button +1 " +xsetwacom set "Tablet Monitor stylus" "Button" "2" "button +2 " +xsetwacom set "Tablet Monitor stylus" "Button" "3" "button +3 " \ No newline at end of file diff --git a/configs/tabset/devices/huion-kamvas-13/profiles/default.sh b/configs/tabset/devices/huion-kamvas-13/profiles/default.sh new file mode 120000 index 0000000..b982e46 --- /dev/null +++ b/configs/tabset/devices/huion-kamvas-13/profiles/default.sh @@ -0,0 +1 @@ +blender.sh \ No newline at end of file diff --git a/configs/tabset/devices/huion-kamvas-13/profiles/disabled.sh b/configs/tabset/devices/huion-kamvas-13/profiles/disabled.sh new file mode 100755 index 0000000..46e6ae1 --- /dev/null +++ b/configs/tabset/devices/huion-kamvas-13/profiles/disabled.sh @@ -0,0 +1,18 @@ +# Top three buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 1 "button 0" +xsetwacom --set "Tablet Monitor Pad pad" Button 2 "button 0" +xsetwacom --set "Tablet Monitor Pad pad" Button 3 "button 0" + +# Middle two buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 8 "button 0" +xsetwacom --set "Tablet Monitor Pad pad" Button 9 "button 0" + +# Bottom three buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 10 "button 0" +xsetwacom --set "Tablet Monitor Pad pad" Button 11 "button 0" +xsetwacom --set "Tablet Monitor Pad pad" Button 12 "button 0" + +# Pen buttons +xsetwacom set "Tablet Monitor stylus" "Button" "1" "button +1 " +xsetwacom set "Tablet Monitor stylus" "Button" "2" "button +2 " +xsetwacom set "Tablet Monitor stylus" "Button" "3" "button +3 " diff --git a/configs/tabset/devices/huion-kamvas-13/profiles/gimp.sh b/configs/tabset/devices/huion-kamvas-13/profiles/gimp.sh new file mode 100755 index 0000000..34732ad --- /dev/null +++ b/configs/tabset/devices/huion-kamvas-13/profiles/gimp.sh @@ -0,0 +1,18 @@ +# Top three buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 1 "key +ctrl +z -z -ctrl" +xsetwacom --set "Tablet Monitor Pad pad" Button 2 "key +ctrl +shift +a -a -shift -ctrl" +xsetwacom --set "Tablet Monitor Pad pad" Button 3 "key del" + +# Middle two buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 8 "key shift" +xsetwacom --set "Tablet Monitor Pad pad" Button 9 "key ctrl" + +# Bottom three buttons +xsetwacom --set "Tablet Monitor Pad pad" Button 10 "key +shift +e -e -shift" +xsetwacom --set "Tablet Monitor Pad pad" Button 11 "key p" +xsetwacom --set "Tablet Monitor Pad pad" Button 12 "key f" + +# Pen buttons +xsetwacom set "Tablet Monitor stylus" "Button" "1" "button +1 " +xsetwacom set "Tablet Monitor stylus" "Button" "2" "button +2 " +xsetwacom set "Tablet Monitor stylus" "Button" "3" "button +3 " diff --git a/configs/zsh/prompt.sh b/configs/zsh/prompt.sh index 9ef1dee..cc37d83 100644 --- a/configs/zsh/prompt.sh +++ b/configs/zsh/prompt.sh @@ -1,5 +1,6 @@ # This is some kind of dark magic. # I have no memory of whats going on here, but this has been my config since 2015-ish, so it shall not be touched. +# This was origionally written for crosh, so that may be part of the problem... autoload -U colors && colors NEWLINE=$'\n' diff --git a/install.conf.yaml b/install.conf.yaml index 1ed7a4d..80fa0da 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -9,6 +9,8 @@ ~/.zshrc: path: configs/zsh/.zshrc force: true + ~/.config/tabset/: + path: configs/tabset/** - create: - ~/Downloads From e85777ffa75ae3b38345532b0a913ba97c4991b5 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 18:10:46 -0500 Subject: [PATCH 012/326] no subpath --- install.conf.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/install.conf.yaml b/install.conf.yaml index 80fa0da..1cd1f6c 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -9,8 +9,7 @@ ~/.zshrc: path: configs/zsh/.zshrc force: true - ~/.config/tabset/: - path: configs/tabset/** + ~/.config/tabset: configs/tabset - create: - ~/Downloads From 48a5d271db5f3c3f2ec6981371b9cf173a35d9b0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 18:12:40 -0500 Subject: [PATCH 013/326] Set up some personal-preference stuff --- configs/zsh/.zshrc | 5 ++++- install.conf.yaml | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 98f992f..1202358 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -9,4 +9,7 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" # Load per-host configuration if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then . $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh -fi \ No newline at end of file +fi + +# I always want my ~/bin to be in my PATH +export PATH="$HOME/bin:$PATH" \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index 1cd1f6c..3c50760 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -14,6 +14,8 @@ - create: - ~/Downloads - ~/bin + - ~/projects + - ~/src - shell: - [git submodule update --init --recursive, Installing submodules] \ No newline at end of file From 6c93db488c1e69436e8990ab18117eb2b678577a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 18:26:01 -0500 Subject: [PATCH 014/326] add sdkman support to configs --- configs/zsh/by_host/ewpratten-desktop.sh | 6 +++++- configs/zsh/by_host/ewpratten-laptop.sh | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/configs/zsh/by_host/ewpratten-desktop.sh b/configs/zsh/by_host/ewpratten-desktop.sh index efcbaec..ea06869 100644 --- a/configs/zsh/by_host/ewpratten-desktop.sh +++ b/configs/zsh/by_host/ewpratten-desktop.sh @@ -1 +1,5 @@ -#! /bin/bash \ No newline at end of file +#! /bin/bash + +# SDKMAN! +export SDKMAN_DIR="$HOME/.sdkman" +[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" diff --git a/configs/zsh/by_host/ewpratten-laptop.sh b/configs/zsh/by_host/ewpratten-laptop.sh index efcbaec..1ecab94 100644 --- a/configs/zsh/by_host/ewpratten-laptop.sh +++ b/configs/zsh/by_host/ewpratten-laptop.sh @@ -1 +1,5 @@ -#! /bin/bash \ No newline at end of file +#! /bin/bash + +# SDKMAN! +export SDKMAN_DIR="$HOME/.sdkman" +[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" \ No newline at end of file From 4594ce53a22562b47087e6ab4f8bd7ec3afb3665 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 18:35:09 -0500 Subject: [PATCH 015/326] Add keybinds to shells --- configs/zsh/.zshrc | 1 + configs/zsh/keybinds.sh | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 configs/zsh/keybinds.sh diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 1202358..5ffce37 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -5,6 +5,7 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" # Load my custom prompt and macros . $EWCONFIG_ROOT/configs/zsh/prompt.sh . $EWCONFIG_ROOT/configs/zsh/macros.sh +. $EWCONFIG_ROOT/configs/zsh/keybinds.sh # Load per-host configuration if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then diff --git a/configs/zsh/keybinds.sh b/configs/zsh/keybinds.sh new file mode 100644 index 0000000..2e8d184 --- /dev/null +++ b/configs/zsh/keybinds.sh @@ -0,0 +1,23 @@ +### ctrl+arrows +bindkey "\e[1;5C" forward-word +bindkey "\e[1;5D" backward-word +# urxvt +bindkey "\eOc" forward-word +bindkey "\eOd" backward-word + +### ctrl+delete +bindkey "\e[3;5~" kill-word +# urxvt +bindkey "\e[3^" kill-word + +### ctrl+backspace +bindkey '^H' backward-kill-word + +### ctrl+shift+delete +bindkey "\e[3;6~" kill-line +# urxvt +bindkey "\e[3@" kill-line + +# Home and end +bindkey "^[[H" beginning-of-line +bindkey "^[[F" end-of-line \ No newline at end of file From d2ccc615e53d9d8e04538559b34e26f95a8e9dcf Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 22 Feb 2022 19:04:22 -0500 Subject: [PATCH 016/326] Bring back some old autocomplete features --- configs/zsh/.zshrc | 1 + configs/zsh/autocomplete.sh | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 configs/zsh/autocomplete.sh diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 5ffce37..dace0c8 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -6,6 +6,7 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" . $EWCONFIG_ROOT/configs/zsh/prompt.sh . $EWCONFIG_ROOT/configs/zsh/macros.sh . $EWCONFIG_ROOT/configs/zsh/keybinds.sh +. $EWCONFIG_ROOT/configs/zsh/autocomplete.sh # Load per-host configuration if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then diff --git a/configs/zsh/autocomplete.sh b/configs/zsh/autocomplete.sh new file mode 100644 index 0000000..868cd3b --- /dev/null +++ b/configs/zsh/autocomplete.sh @@ -0,0 +1,17 @@ + +# Handles case-insensitive completion +autoload -Uz compinit && compinit +zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' + +# Configure command history +HISTFILE=~/.histfile +HISTSIZE=1000 +SAVEHIST=1000 + +# Allow up arrow to be used to go back in history based on current line contents +autoload -U up-line-or-beginning-search +autoload -U down-line-or-beginning-search +zle -N up-line-or-beginning-search +zle -N down-line-or-beginning-search +bindkey "^[[A" up-line-or-beginning-search # Up +bindkey "^[[B" down-line-or-beginning-search # Down \ No newline at end of file From b09f107ffc313bac9ab682989086dcfdc98fb04b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 23 Feb 2022 10:10:10 -0500 Subject: [PATCH 017/326] remmina --- ...b-8700k-125-industrialbrothers-com.remmina | 69 ++++++++++++++++++ ...b-8700k-139-industrialbrothers-com.remmina | 69 ++++++++++++++++++ ...es_vnc_quick-connect_10-9-0-5-6001.remmina | 73 +++++++++++++++++++ ...devices_vnc_quick-connect_10-9-0-5.remmina | 73 +++++++++++++++++++ install.conf.yaml | 1 + 5 files changed, 285 insertions(+) create mode 100644 configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina create mode 100644 configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina create mode 100644 configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina create mode 100644 configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina diff --git a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina new file mode 100644 index 0000000..ca44191 --- /dev/null +++ b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina @@ -0,0 +1,69 @@ +[remmina] +password=. +gateway_username= +ssh_tunnel_loopback=0 +serialname= +printer_overrides= +name=ib-8700k-125 +console=0 +colordepth=64 +security= +precommand= +disable_fastpath=0 +postcommand= +group=IndustrialBrothers +server=ib-8700k-125.industrialbrothers.com +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +parallelpath= +cert_ignore=0 +gateway_server= +serialpermissive=0 +protocol=RDP +old-license=0 +ssh_tunnel_password= +resolution_mode=2 +disableautoreconnect=0 +loadbalanceinfo= +clientname= +clientbuild= +resolution_width=0 +relax-order-checks=0 +username=epratten +gateway_domain= +serialdriver= +domain= +gateway_password= +smartcardname= +serialpath= +exec= +enable-autostart=0 +shareprinter=0 +ssh_tunnel_passphrase= +disablepasswordstoring=0 +quality=0 +shareparallel=0 +parallelname= +execpath= +shareserial=0 +sharefolder= +sharesmartcard=0 +ssh_tunnel_username= +resolution_height=0 +useproxyenv=0 +microphone=0 +gwtransp=http +ssh_tunnel_privatekey= +ssh_tunnel_server= +ignore-tls-errors=1 +gateway_usage=0 +ssh_tunnel_auth=2 +sound=off +window_height=525 +last_success=20210825 +window_maximize=1 +window_width=839 +scale=2 +viewmode=1 +keyboard_grab=0 diff --git a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina new file mode 100644 index 0000000..17ad902 --- /dev/null +++ b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina @@ -0,0 +1,69 @@ +[remmina] +password=. +gateway_username= +window_height=525 +scale=2 +ssh_tunnel_loopback=0 +serialname= +printer_overrides= +name=ib-8700k-139 +console=0 +colordepth=64 +security= +precommand= +disable_fastpath=0 +postcommand= +group=IndustrialBrothers +server=ib-8700k-139.industrialbrothers.com +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +parallelpath= +cert_ignore=0 +gateway_server= +serialpermissive=0 +protocol=RDP +ssh_tunnel_password= +old-license=0 +resolution_mode=2 +disableautoreconnect=0 +loadbalanceinfo= +clientname= +clientbuild= +resolution_width=0 +relax-order-checks=0 +username=epratten +gateway_domain= +serialdriver= +domain= +gateway_password= +smartcardname= +exec= +serialpath= +last_success=20220222 +enable-autostart=0 +shareprinter=0 +shareparallel=0 +ssh_tunnel_passphrase= +quality=0 +disablepasswordstoring=0 +parallelname= +viewmode=1 +ssh_tunnel_auth=2 +shareserial=0 +sharefolder= +execpath= +sharesmartcard=0 +ssh_tunnel_username= +resolution_height=0 +useproxyenv=0 +microphone=0 +keyboard_grab=0 +gwtransp=http +ssh_tunnel_privatekey= +ssh_tunnel_server= +ignore-tls-errors=1 +window_maximize=1 +gateway_usage=0 +window_width=839 +sound=off diff --git a/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina b/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina new file mode 100644 index 0000000..c63432f --- /dev/null +++ b/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina @@ -0,0 +1,73 @@ +[remmina] +password=. +gateway_username= +window_height=525 +ssh_tunnel_loopback=0 +serialname= +printer_overrides= +name=Quick Connect +console=0 +colordepth=8 +security= +precommand= +disable_fastpath=0 +postcommand= +group=VPN Devices +server=10.9.0.5:6001 +viewonly=0 +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +parallelpath= +cert_ignore=0 +serialpermissive=0 +gateway_server= +protocol=VNC +ssh_tunnel_password= +old-license=0 +resolution_mode=2 +disableautoreconnect=0 +loadbalanceinfo= +clientbuild= +clientname= +resolution_width=0 +relax-order-checks=0 +username=pi +gateway_domain= +showcursor=0 +gateway_password= +serialdriver= +domain= +smartcardname= +exec= +serialpath= +disableserverinput=0 +last_success=20211207 +enable-autostart=0 +shareprinter=0 +shareparallel=0 +ssh_tunnel_passphrase= +proxy= +quality=0 +disablepasswordstoring=0 +parallelname= +viewmode=1 +ssh_tunnel_auth=2 +shareserial=0 +ssh_tunnel_username= +sharesmartcard=0 +sharefolder= +execpath= +resolution_height=0 +useproxyenv=0 +microphone=0 +keymap= +gwtransp=http +ssh_tunnel_privatekey= +ssh_tunnel_server= +ignore-tls-errors=1 +window_maximize=1 +gateway_usage=0 +disableencryption=0 +window_width=640 +sound=off diff --git a/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina b/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina new file mode 100644 index 0000000..1b74303 --- /dev/null +++ b/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina @@ -0,0 +1,73 @@ +[remmina] +password=. +gateway_username= +window_height=525 +ssh_tunnel_loopback=0 +serialname= +printer_overrides= +name=Quick Connect +console=0 +colordepth=8 +security= +precommand= +disable_fastpath=0 +postcommand= +group=VPN Devices +server=10.9.0.5 +viewonly=0 +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +parallelpath= +cert_ignore=0 +serialpermissive=0 +gateway_server= +protocol=VNC +ssh_tunnel_password= +old-license=0 +resolution_mode=2 +disableautoreconnect=0 +loadbalanceinfo= +clientbuild= +clientname= +resolution_width=0 +relax-order-checks=0 +username=pi +gateway_domain= +showcursor=0 +gateway_password= +serialdriver= +domain= +smartcardname= +exec= +serialpath= +disableserverinput=0 +last_success=20211207 +enable-autostart=0 +shareprinter=0 +shareparallel=0 +ssh_tunnel_passphrase= +proxy= +quality=0 +disablepasswordstoring=0 +parallelname= +viewmode=1 +ssh_tunnel_auth=2 +shareserial=0 +ssh_tunnel_username= +sharesmartcard=0 +sharefolder= +execpath= +resolution_height=0 +useproxyenv=0 +microphone=0 +keymap= +gwtransp=http +ssh_tunnel_privatekey= +ssh_tunnel_server= +ignore-tls-errors=1 +window_maximize=1 +gateway_usage=0 +disableencryption=0 +window_width=640 +sound=off diff --git a/install.conf.yaml b/install.conf.yaml index 3c50760..7ef76d6 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -10,6 +10,7 @@ path: configs/zsh/.zshrc force: true ~/.config/tabset: configs/tabset + ~/.local/share/remmina: configs/remmina/hosts - create: - ~/Downloads From 8e7e28310137b24e58283f0da8f88cf91022b0c1 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 23 Feb 2022 10:12:31 -0500 Subject: [PATCH 018/326] pass --- ...p_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina | 4 ++-- ...p_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina | 2 +- .../hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina index ca44191..d152f72 100644 --- a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina +++ b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina @@ -1,5 +1,5 @@ [remmina] -password=. +password= gateway_username= ssh_tunnel_loopback=0 serialname= @@ -52,7 +52,7 @@ sharesmartcard=0 ssh_tunnel_username= resolution_height=0 useproxyenv=0 -microphone=0 +microphone= gwtransp=http ssh_tunnel_privatekey= ssh_tunnel_server= diff --git a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina index 17ad902..9828a1e 100644 --- a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina +++ b/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina @@ -57,7 +57,7 @@ sharesmartcard=0 ssh_tunnel_username= resolution_height=0 useproxyenv=0 -microphone=0 +microphone= keyboard_grab=0 gwtransp=http ssh_tunnel_privatekey= diff --git a/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina b/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina index 1b74303..cde7012 100644 --- a/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina +++ b/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina @@ -1,5 +1,5 @@ [remmina] -password=. +password= gateway_username= window_height=525 ssh_tunnel_loopback=0 From 004acad8d1b542172f5b2855a990ca0a3596851b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 25 Mar 2022 12:21:05 -0400 Subject: [PATCH 019/326] update ssh config --- configs/ssh/config | 10 +++++++++- configs/zsh/.zshrc | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index bc600ad..79a237f 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -1,4 +1,3 @@ - # Personal servers Host rtl-netlink HostName netlink.local @@ -14,6 +13,14 @@ Host gw-ca-tor-01 Host hp-desktop Hostname 10.9.0.12 +Host ewpratten-laptop + Hostname 10.9.0.2 + User ewpratten + +Host ewpratten-desktop + Hostname 10.9.0.9 + User ewpratten + # Github SSH adapter for restricted networks Host github.com HostName ssh.github.com @@ -68,3 +75,4 @@ Host atlas Host sheridan-cpanel User prattene HostName cpanel.prattene.dev.fast.sheridanc.on.ca + diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index dace0c8..65f0cdb 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -14,4 +14,7 @@ if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then fi # I always want my ~/bin to be in my PATH -export PATH="$HOME/bin:$PATH" \ No newline at end of file +export PATH="$HOME/bin:$PATH" +#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!! +export SDKMAN_DIR="$HOME/.sdkman" +[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" From 32d6f346dc523c21c9a5f927753e08f4baf0c25c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 1 Aug 2022 09:34:27 -0400 Subject: [PATCH 020/326] delete key --- ...group_rdp_quick-connect_10-80-55-8.remmina | 92 +++++++++++++++++++ configs/zsh/by_host/ewpratten-laptop.sh | 13 ++- configs/zsh/keybinds.sh | 5 +- 3 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 configs/remmina/hosts/group_rdp_quick-connect_10-80-55-8.remmina diff --git a/configs/remmina/hosts/group_rdp_quick-connect_10-80-55-8.remmina b/configs/remmina/hosts/group_rdp_quick-connect_10-80-55-8.remmina new file mode 100644 index 0000000..a51f3f5 --- /dev/null +++ b/configs/remmina/hosts/group_rdp_quick-connect_10-80-55-8.remmina @@ -0,0 +1,92 @@ +[remmina] +password=. +gateway_username= +notes_text= +vc= +preferipv6=0 +ssh_tunnel_loopback=0 +serialname= +sound=off +printer_overrides= +name=Quick Connect +console=0 +colordepth=99 +security= +precommand= +disable_fastpath=0 +left-handed=0 +postcommand= +multitransport=0 +group= +server=10.80.55.8 +ssh_tunnel_certfile= +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +audio-output= +parallelpath= +monitorids= +cert_ignore=0 +gateway_server= +serialpermissive=0 +protocol=RDP +old-license=0 +ssh_tunnel_password= +resolution_mode=2 +pth= +loadbalanceinfo= +disableautoreconnect=0 +clientname= +clientbuild= +resolution_width=0 +drive= +relax-order-checks=0 +username=pi +base-cred-for-gw=0 +gateway_domain= +network=none +rdp2tcp= +gateway_password= +serialdriver= +domain= +profile-lock=0 +rdp_reconnect_attempts= +restricted-admin=0 +multimon=0 +exec= +smartcardname= +serialpath= +enable-autostart=0 +usb= +shareprinter=0 +ssh_tunnel_passphrase= +shareparallel=0 +disablepasswordstoring=0 +quality=0 +span=0 +parallelname= +ssh_tunnel_auth=0 +keymap= +ssh_tunnel_username= +execpath= +shareserial=0 +resolution_height=0 +timeout= +useproxyenv=0 +sharesmartcard=0 +freerdp_log_filters= +microphone= +dvc= +ssh_tunnel_privatekey= +gwtransp=http +ssh_tunnel_server= +ignore-tls-errors=1 +disable-smooth-scrolling=0 +gateway_usage=0 +websockets=0 +freerdp_log_level=INFO +window_height=480 +window_maximize=1 +window_width=640 +scale=2 +viewmode=1 diff --git a/configs/zsh/by_host/ewpratten-laptop.sh b/configs/zsh/by_host/ewpratten-laptop.sh index 1ecab94..2d52610 100644 --- a/configs/zsh/by_host/ewpratten-laptop.sh +++ b/configs/zsh/by_host/ewpratten-laptop.sh @@ -1,5 +1,16 @@ #! /bin/bash +# Various custom-compiled libs live here +export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH + # SDKMAN! export SDKMAN_DIR="$HOME/.sdkman" -[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" \ No newline at end of file +[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" + +# NVM +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion + +# Flutter +export PATH="$PATH:$HOME/development/flutter/bin" diff --git a/configs/zsh/keybinds.sh b/configs/zsh/keybinds.sh index 2e8d184..9459345 100644 --- a/configs/zsh/keybinds.sh +++ b/configs/zsh/keybinds.sh @@ -20,4 +20,7 @@ bindkey "\e[3@" kill-line # Home and end bindkey "^[[H" beginning-of-line -bindkey "^[[F" end-of-line \ No newline at end of file +bindkey "^[[F" end-of-line + +# Delete +bindkey "^[[3~" delete-char From f199a5a20b4cd20277b8f655460873a5cabb22ac Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 18 Aug 2022 12:24:16 -0400 Subject: [PATCH 021/326] vimrc stuff --- README.md | 15 +++ configs/nvim/init.vim | 33 ++++++ .../group_rdp_pi-tnc_pi-tnc-local.remmina | 101 ++++++++++++++++++ ...466-va3zza-com_193-148-251-11-5900.remmina | 38 +++++++ install.conf.yaml | 1 + 5 files changed, 188 insertions(+) create mode 100644 README.md create mode 100644 configs/nvim/init.vim create mode 100644 configs/remmina/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina create mode 100644 configs/remmina/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina diff --git a/README.md b/README.md new file mode 100644 index 0000000..d26b161 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# ewconfig: My dotfiles + +## Neovim + +```sh +sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \ + https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' +``` + +And in `nvim`, run + +```text +:PlugInstall +:Copilot setup +``` diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim new file mode 100644 index 0000000..6ad9b45 --- /dev/null +++ b/configs/nvim/init.vim @@ -0,0 +1,33 @@ + +" Enable mouse usage +set mouse=a + +" Tab size +set tabstop=4 +set shiftwidth=4 +set expandtab + +" Force VIM to use system clipboard +set clipboard=unnamedplus + +" Enable per-project vimrc files +set exrc +set secure + +" This is where the plugins be +call plug#begin() + +Plug 'github/copilot.vim' +Plug 'tpope/vim-fugitive' +Plug 'tpope/vim-surround' + +" And this is where the plugins no longer be +call plug#end() + +" Enable filetype plugins +set nocompatible +filetype plugin on +syntax on + +" Enable rainbow +let g:rainbow_active = 1 \ No newline at end of file diff --git a/configs/remmina/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina b/configs/remmina/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina new file mode 100644 index 0000000..bb186b6 --- /dev/null +++ b/configs/remmina/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina @@ -0,0 +1,101 @@ +[remmina] +password=. +gateway_username= +notes_text= +vc= +preferipv6=0 +ssh_tunnel_loopback=0 +serialname= +sound=off +disableserverbell=0 +printer_overrides= +name=pi-tnc +console=0 +colordepth=32 +security= +precommand= +disable_fastpath=0 +tightencoding=0 +left-handed=0 +multitransport=0 +postcommand= +group= +server=pi-tnc.local +viewonly=0 +ssh_tunnel_certfile= +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +parallelpath= +audio-output= +monitorids= +cert_ignore=0 +gateway_server= +serialpermissive=0 +ssh_tunnel_password= +old-license=0 +protocol=RDP +resolution_mode=2 +pth= +loadbalanceinfo= +disableautoreconnect=0 +clientbuild= +clientname= +disablesmoothscrolling=0 +resolution_width=0 +drive= +username=ewpratten +relax-order-checks=0 +base-cred-for-gw=0 +profile-lock=0 +showcursor=0 +network=none +gateway_domain= +serialdriver= +rdp2tcp= +gateway_password= +rdp_reconnect_attempts= +restricted-admin=0 +multimon=0 +domain= +disableserverinput=0 +exec= +enable-autostart=0 +smartcardname= +serialpath= +ssh_tunnel_passphrase= +viewmode=1 +proxy= +quality=2 +usb= +shareprinter=0 +disablepasswordstoring=0 +span=0 +parallelname= +shareparallel=0 +disableencryption=0 +keymap= +ssh_tunnel_username= +ssh_tunnel_auth=0 +shareserial=0 +resolution_height=0 +timeout= +useproxyenv=0 +sharesmartcard=0 +execpath= +microphone= +freerdp_log_filters= +ssh_tunnel_privatekey= +window_maximize=1 +encodings= +ignore-tls-errors=1 +ssh_tunnel_server= +dvc= +gateway_usage=0 +gwtransp=http +websockets=0 +freerdp_log_level=INFO +disable-smooth-scrolling=0 +window_height=754 +window_width=1093 +scale=2 diff --git a/configs/remmina/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina b/configs/remmina/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina new file mode 100644 index 0000000..4a49d94 --- /dev/null +++ b/configs/remmina/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina @@ -0,0 +1,38 @@ +[remmina] +encodings= +ssh_tunnel_privatekey= +name=edge-004-kansas-us.na.as204466.va3zza.com +colordepth=32 +password=. +quality=2 +disablesmoothscrolling=0 +precommand= +ssh_tunnel_enabled=0 +viewonly=0 +disableserverinput=0 +ignore-tls-errors=1 +postcommand= +tightencoding=0 +server=193.148.251.11:5900 +disablepasswordstoring=0 +ssh_tunnel_username= +disableclipboard=0 +disableserverbell=0 +ssh_tunnel_password= +profile-lock=0 +showcursor=0 +enable-autostart=0 +disableencryption=0 +ssh_tunnel_loopback=0 +group= +notes_text= +ssh_tunnel_server= +ssh_tunnel_certfile= +keymap= +ssh_tunnel_auth=0 +proxy= +protocol=VNC +username=root@pam +ssh_tunnel_passphrase= +viewmode=1 +window_maximize=0 diff --git a/install.conf.yaml b/install.conf.yaml index 7ef76d6..e394b04 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -11,6 +11,7 @@ force: true ~/.config/tabset: configs/tabset ~/.local/share/remmina: configs/remmina/hosts + ~/.config/nvim: configs/nvim - create: - ~/Downloads From d10c4d9c25d8bd68e348b23432f471c1eb3e9a75 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 29 Aug 2022 09:51:56 -0400 Subject: [PATCH 022/326] nkill --- .../hosts/group_rdp_pi-tnc_10-80-55-8.remmina | 102 ++++++++++++++++++ configs/zsh/macros.sh | 7 +- 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 configs/remmina/hosts/group_rdp_pi-tnc_10-80-55-8.remmina diff --git a/configs/remmina/hosts/group_rdp_pi-tnc_10-80-55-8.remmina b/configs/remmina/hosts/group_rdp_pi-tnc_10-80-55-8.remmina new file mode 100644 index 0000000..adfdb69 --- /dev/null +++ b/configs/remmina/hosts/group_rdp_pi-tnc_10-80-55-8.remmina @@ -0,0 +1,102 @@ +[remmina] +password=. +gateway_username= +notes_text= +vc= +preferipv6=0 +ssh_tunnel_loopback=0 +serialname= +tls-seclevel= +sound=off +disableserverbell=0 +printer_overrides= +name=PI TNC +console=0 +colordepth=32 +security= +precommand= +disable_fastpath=0 +tightencoding=0 +left-handed=0 +multitransport=0 +postcommand= +group= +server=10.80.55.8 +viewonly=0 +ssh_tunnel_certfile= +glyph-cache=0 +ssh_tunnel_enabled=0 +disableclipboard=0 +parallelpath= +audio-output= +monitorids= +cert_ignore=0 +gateway_server= +serialpermissive=0 +ssh_tunnel_password= +old-license=0 +protocol=RDP +resolution_mode=2 +pth= +loadbalanceinfo= +disableautoreconnect=0 +clientname= +clientbuild= +disablesmoothscrolling=0 +resolution_width=0 +drive= +username=ewpratten +relax-order-checks=0 +base-cred-for-gw=0 +profile-lock=0 +showcursor=0 +network=none +gateway_domain= +serialdriver= +rdp2tcp= +gateway_password= +rdp_reconnect_attempts= +restricted-admin=0 +multimon=0 +domain= +disableserverinput=0 +exec= +enable-autostart=0 +smartcardname= +serialpath= +ssh_tunnel_passphrase= +viewmode=1 +proxy= +quality=2 +usb= +shareprinter=0 +disablepasswordstoring=0 +span=0 +parallelname= +shareparallel=0 +disableencryption=0 +ssh_tunnel_auth=0 +ssh_tunnel_username= +execpath= +keymap= +resolution_height=0 +shareserial=0 +useproxyenv=0 +sharesmartcard=0 +freerdp_log_filters= +microphone= +timeout= +ssh_tunnel_privatekey= +window_maximize=1 +encodings= +ignore-tls-errors=1 +ssh_tunnel_server= +dvc= +gateway_usage=0 +gwtransp=http +websockets=0 +freerdp_log_level=INFO +disable-smooth-scrolling=0 +window_height=480 +window_width=640 +scale=2 diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index dae2241..22ad3e6 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -8,6 +8,11 @@ alias p4='ping 8.8.8.8 -c 4' alias quickhttp='sudo python -m SimpleHTTPServer 443' alias zshreload="source ~/.zshrc" +# Kill via pgrep +nkill() { + kill -9 $(pgrep $1) +} + # Makes a directory, then moves into it mkcd() { if [ $# != 1 ]; then @@ -37,4 +42,4 @@ extract() { else echo "'$1' is not a valid file!" fi -} \ No newline at end of file +} From 2be2733c1bdad6f7d4f238c200ff302cf4a7b73f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 29 Aug 2022 11:13:02 -0400 Subject: [PATCH 023/326] Use colors to show remote connections --- configs/zsh/prompt.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/configs/zsh/prompt.sh b/configs/zsh/prompt.sh index cc37d83..62b6cec 100644 --- a/configs/zsh/prompt.sh +++ b/configs/zsh/prompt.sh @@ -4,7 +4,15 @@ autoload -U colors && colors NEWLINE=$'\n' -export PROMPT="%{$fg[green]%}%n@%M %{$fg[cyan]%}%~ $ %{$reset_color%}" + +# Use colors to signal local vs remote connections +if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then + HOST_COLOR="yellow" +else + HOST_COLOR="green" +fi + +export PROMPT="%{$fg[$HOST_COLOR]%}%n@%M %{$fg[cyan]%}%~ $ %{$reset_color%}" setopt prompt_subst autoload -Uz vcs_info zstyle ':vcs_info:*' actionformats \ From ce71de8abd30ce8fad10592c39058608a2db68cd Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 11 Sep 2022 22:58:03 -0400 Subject: [PATCH 024/326] catto! --- configs/scripts/catto | 58 +++++++++++++++++++++++++++++++++++++++++++ configs/zsh/.zshrc | 3 --- install.conf.yaml | 18 ++++++++------ 3 files changed, 69 insertions(+), 10 deletions(-) create mode 100755 configs/scripts/catto diff --git a/configs/scripts/catto b/configs/scripts/catto new file mode 100755 index 0000000..4cbff55 --- /dev/null +++ b/configs/scripts/catto @@ -0,0 +1,58 @@ +#! /usr/bin/env python3 +import sys +import requests +import json +import argparse +import os +import tempfile +from pathlib import Path +import netrc + +def main() -> int: + ap = argparse.ArgumentParser() + ap.add_argument("image", help="Image to upload") + ap.add_argument("--no-compress", help="Don't compress the image", action="store_true") + args = ap.parse_args() + + # Load the API key from the .netrc file + if "catto.pictures" not in netrc.netrc().hosts: + print("No catto.pictures entry in .netrc file") + return 1 + login, account, password = netrc.netrc().authenticators("catto.pictures") + + # Parse the image to a path + image_path = Path(args.image) + + # Ensure the file actually exists + if not image_path.exists(): + print("File not found", file=sys.stderr) + return 1 + + # Compres the image to a temporary file + with tempfile.NamedTemporaryFile(suffix=image_path.suffix) as temp: + # Compress + if not args.no_compress: + os.system(f"convert {image_path} -quality 25% {temp.name}") + image_path = Path(temp.name) + + # Strip all exif data + os.system(f"exiftool -EXIF= {image_path}") + + # Upload the image + with open(image_path, "rb") as f: + r = requests.post( + "https://upload.catto.pictures", + files={"image": (temp.name, f, f"image/{image_path.suffix[1:]}")}, + headers={ + "Authorization": password, + "Domain": "img.ewpratten.com", + } + ) + if r.status_code != 200: + print(f"Error uploading image:\n{r.text}", file=sys.stderr) + return 1 + print(json.loads(r.text)["url"]) + +if __name__ == "__main__": + sys.exit(main()) + diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 65f0cdb..dc1bab6 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -15,6 +15,3 @@ fi # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" -#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!! -export SDKMAN_DIR="$HOME/.sdkman" -[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" diff --git a/install.conf.yaml b/install.conf.yaml index e394b04..fc190ac 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -4,6 +4,12 @@ - clean: ['~'] +- create: + - ~/Downloads + - ~/bin + - ~/projects + - ~/src + - link: ~/.gitconfig: configs/git/.gitconfig ~/.zshrc: @@ -12,12 +18,10 @@ ~/.config/tabset: configs/tabset ~/.local/share/remmina: configs/remmina/hosts ~/.config/nvim: configs/nvim - -- create: - - ~/Downloads - - ~/bin - - ~/projects - - ~/src + ~/bin/catto: + path: configs/scripts/catto + mode: 755 - shell: - - [git submodule update --init --recursive, Installing submodules] \ No newline at end of file + - [git submodule update --init --recursive, Installing submodules] + - [chmod +x configs/scripts/catto, Making catto executable] \ No newline at end of file From 4834741d75ce0d806b61273ffc6695b5adc4c075 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 27 Sep 2022 10:35:38 -0400 Subject: [PATCH 025/326] launch info --- configs/zsh/.zshrc | 3 +++ configs/zsh/info.sh | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 configs/zsh/info.sh diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index dc1bab6..940a6b0 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -13,5 +13,8 @@ if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then . $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh fi +# Show some host info +. $EWCONFIG_ROOT/configs/zsh/info.sh + # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" diff --git a/configs/zsh/info.sh b/configs/zsh/info.sh new file mode 100644 index 0000000..53076b8 --- /dev/null +++ b/configs/zsh/info.sh @@ -0,0 +1,2 @@ +echo "$fg[$HOST_COLOR]Platform:$reset_color $(uname -o) $(uname -r)" +echo "$fg[$HOST_COLOR]Uptime:$reset_color $(uptime -p)" \ No newline at end of file From 5ffe274abdfd36d14a28c5edba98e799d90e26cb Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 4 Oct 2022 22:15:21 -0400 Subject: [PATCH 026/326] neovim stuffs --- configs/nvim/init.vim | 32 +++++++++++++++++++++++++++++++- configs/scripts/catto | 2 +- configs/zsh/macros.sh | 8 ++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 6ad9b45..d726d20 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -1,4 +1,7 @@ +" Syntax highlighting +syntax on + " Enable mouse usage set mouse=a @@ -7,6 +10,16 @@ set tabstop=4 set shiftwidth=4 set expandtab +" VSCode-style selection indenting +nnoremap >>_ +nnoremap <<_ +inoremap +vnoremap >gv +vnoremap int: print("File not found", file=sys.stderr) return 1 - # Compres the image to a temporary file + # Compress the image to a temporary file with tempfile.NamedTemporaryFile(suffix=image_path.suffix) as temp: # Compress if not args.no_compress: diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 22ad3e6..ea8f9e2 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -7,6 +7,7 @@ alias cls=clear alias p4='ping 8.8.8.8 -c 4' alias quickhttp='sudo python -m SimpleHTTPServer 443' alias zshreload="source ~/.zshrc" +alias wg-easykeys="wg genkey | tee >(wg pubkey)" # Kill via pgrep nkill() { @@ -22,6 +23,13 @@ mkcd() { fi } +# Sources a .env +source_env() { + env=${1:-.env} + [ ! -f "${env}" ] && { echo "Env file ${env} doesn't exist"; return 1; } + eval $(sed -e '/^\s*$/d' -e '/^\s*#/d' -e 's/=/="/' -e 's/$/"/' -e 's/^/export /' "${env}") +} + # Auto-extract anything extract() { if [ -f $1 ]; then From d1b7ad9491efceda2080a7de0fddf322500fe759 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 4 Oct 2022 22:19:50 -0400 Subject: [PATCH 027/326] rm remm --- .../hosts/group_rdp_pi-tnc_10-80-55-8.remmina | 0 .../hosts/group_rdp_pi-tnc_pi-tnc-local.remmina | 0 .../hosts/group_rdp_quick-connect_10-80-55-8.remmina | 0 ...4-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina | 0 ...s_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina | 0 ...s_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina | 0 .../hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina | 0 .../hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename configs/{remmina => remmina_}/hosts/group_rdp_pi-tnc_10-80-55-8.remmina (100%) rename configs/{remmina => remmina_}/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina (100%) rename configs/{remmina => remmina_}/hosts/group_rdp_quick-connect_10-80-55-8.remmina (100%) rename configs/{remmina => remmina_}/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina (100%) rename configs/{remmina => remmina_}/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina (100%) rename configs/{remmina => remmina_}/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina (100%) rename configs/{remmina => remmina_}/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina (100%) rename configs/{remmina => remmina_}/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina (100%) diff --git a/configs/remmina/hosts/group_rdp_pi-tnc_10-80-55-8.remmina b/configs/remmina_/hosts/group_rdp_pi-tnc_10-80-55-8.remmina similarity index 100% rename from configs/remmina/hosts/group_rdp_pi-tnc_10-80-55-8.remmina rename to configs/remmina_/hosts/group_rdp_pi-tnc_10-80-55-8.remmina diff --git a/configs/remmina/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina b/configs/remmina_/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina similarity index 100% rename from configs/remmina/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina rename to configs/remmina_/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina diff --git a/configs/remmina/hosts/group_rdp_quick-connect_10-80-55-8.remmina b/configs/remmina_/hosts/group_rdp_quick-connect_10-80-55-8.remmina similarity index 100% rename from configs/remmina/hosts/group_rdp_quick-connect_10-80-55-8.remmina rename to configs/remmina_/hosts/group_rdp_quick-connect_10-80-55-8.remmina diff --git a/configs/remmina/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina b/configs/remmina_/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina similarity index 100% rename from configs/remmina/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina rename to configs/remmina_/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina diff --git a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina b/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina similarity index 100% rename from configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina rename to configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina diff --git a/configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina b/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina similarity index 100% rename from configs/remmina/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina rename to configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina diff --git a/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina b/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina similarity index 100% rename from configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina rename to configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina diff --git a/configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina b/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina similarity index 100% rename from configs/remmina/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina rename to configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina From 5a4c3d57015597186efb1058092164aa5ee48149 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 4 Oct 2022 22:20:22 -0400 Subject: [PATCH 028/326] rm --- .../hosts/group_rdp_pi-tnc_10-80-55-8.remmina | 102 ------------------ .../group_rdp_pi-tnc_pi-tnc-local.remmina | 101 ----------------- ...group_rdp_quick-connect_10-80-55-8.remmina | 92 ---------------- ...466-va3zza-com_193-148-251-11-5900.remmina | 38 ------- ...b-8700k-125-industrialbrothers-com.remmina | 69 ------------ ...b-8700k-139-industrialbrothers-com.remmina | 69 ------------ ...es_vnc_quick-connect_10-9-0-5-6001.remmina | 73 ------------- ...devices_vnc_quick-connect_10-9-0-5.remmina | 73 ------------- 8 files changed, 617 deletions(-) delete mode 100644 configs/remmina_/hosts/group_rdp_pi-tnc_10-80-55-8.remmina delete mode 100644 configs/remmina_/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina delete mode 100644 configs/remmina_/hosts/group_rdp_quick-connect_10-80-55-8.remmina delete mode 100644 configs/remmina_/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina delete mode 100644 configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina delete mode 100644 configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina delete mode 100644 configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina delete mode 100644 configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina diff --git a/configs/remmina_/hosts/group_rdp_pi-tnc_10-80-55-8.remmina b/configs/remmina_/hosts/group_rdp_pi-tnc_10-80-55-8.remmina deleted file mode 100644 index adfdb69..0000000 --- a/configs/remmina_/hosts/group_rdp_pi-tnc_10-80-55-8.remmina +++ /dev/null @@ -1,102 +0,0 @@ -[remmina] -password=. -gateway_username= -notes_text= -vc= -preferipv6=0 -ssh_tunnel_loopback=0 -serialname= -tls-seclevel= -sound=off -disableserverbell=0 -printer_overrides= -name=PI TNC -console=0 -colordepth=32 -security= -precommand= -disable_fastpath=0 -tightencoding=0 -left-handed=0 -multitransport=0 -postcommand= -group= -server=10.80.55.8 -viewonly=0 -ssh_tunnel_certfile= -glyph-cache=0 -ssh_tunnel_enabled=0 -disableclipboard=0 -parallelpath= -audio-output= -monitorids= -cert_ignore=0 -gateway_server= -serialpermissive=0 -ssh_tunnel_password= -old-license=0 -protocol=RDP -resolution_mode=2 -pth= -loadbalanceinfo= -disableautoreconnect=0 -clientname= -clientbuild= -disablesmoothscrolling=0 -resolution_width=0 -drive= -username=ewpratten -relax-order-checks=0 -base-cred-for-gw=0 -profile-lock=0 -showcursor=0 -network=none -gateway_domain= -serialdriver= -rdp2tcp= -gateway_password= -rdp_reconnect_attempts= -restricted-admin=0 -multimon=0 -domain= -disableserverinput=0 -exec= -enable-autostart=0 -smartcardname= -serialpath= -ssh_tunnel_passphrase= -viewmode=1 -proxy= -quality=2 -usb= -shareprinter=0 -disablepasswordstoring=0 -span=0 -parallelname= -shareparallel=0 -disableencryption=0 -ssh_tunnel_auth=0 -ssh_tunnel_username= -execpath= -keymap= -resolution_height=0 -shareserial=0 -useproxyenv=0 -sharesmartcard=0 -freerdp_log_filters= -microphone= -timeout= -ssh_tunnel_privatekey= -window_maximize=1 -encodings= -ignore-tls-errors=1 -ssh_tunnel_server= -dvc= -gateway_usage=0 -gwtransp=http -websockets=0 -freerdp_log_level=INFO -disable-smooth-scrolling=0 -window_height=480 -window_width=640 -scale=2 diff --git a/configs/remmina_/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina b/configs/remmina_/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina deleted file mode 100644 index bb186b6..0000000 --- a/configs/remmina_/hosts/group_rdp_pi-tnc_pi-tnc-local.remmina +++ /dev/null @@ -1,101 +0,0 @@ -[remmina] -password=. -gateway_username= -notes_text= -vc= -preferipv6=0 -ssh_tunnel_loopback=0 -serialname= -sound=off -disableserverbell=0 -printer_overrides= -name=pi-tnc -console=0 -colordepth=32 -security= -precommand= -disable_fastpath=0 -tightencoding=0 -left-handed=0 -multitransport=0 -postcommand= -group= -server=pi-tnc.local -viewonly=0 -ssh_tunnel_certfile= -glyph-cache=0 -ssh_tunnel_enabled=0 -disableclipboard=0 -parallelpath= -audio-output= -monitorids= -cert_ignore=0 -gateway_server= -serialpermissive=0 -ssh_tunnel_password= -old-license=0 -protocol=RDP -resolution_mode=2 -pth= -loadbalanceinfo= -disableautoreconnect=0 -clientbuild= -clientname= -disablesmoothscrolling=0 -resolution_width=0 -drive= -username=ewpratten -relax-order-checks=0 -base-cred-for-gw=0 -profile-lock=0 -showcursor=0 -network=none -gateway_domain= -serialdriver= -rdp2tcp= -gateway_password= -rdp_reconnect_attempts= -restricted-admin=0 -multimon=0 -domain= -disableserverinput=0 -exec= -enable-autostart=0 -smartcardname= -serialpath= -ssh_tunnel_passphrase= -viewmode=1 -proxy= -quality=2 -usb= -shareprinter=0 -disablepasswordstoring=0 -span=0 -parallelname= -shareparallel=0 -disableencryption=0 -keymap= -ssh_tunnel_username= -ssh_tunnel_auth=0 -shareserial=0 -resolution_height=0 -timeout= -useproxyenv=0 -sharesmartcard=0 -execpath= -microphone= -freerdp_log_filters= -ssh_tunnel_privatekey= -window_maximize=1 -encodings= -ignore-tls-errors=1 -ssh_tunnel_server= -dvc= -gateway_usage=0 -gwtransp=http -websockets=0 -freerdp_log_level=INFO -disable-smooth-scrolling=0 -window_height=754 -window_width=1093 -scale=2 diff --git a/configs/remmina_/hosts/group_rdp_quick-connect_10-80-55-8.remmina b/configs/remmina_/hosts/group_rdp_quick-connect_10-80-55-8.remmina deleted file mode 100644 index a51f3f5..0000000 --- a/configs/remmina_/hosts/group_rdp_quick-connect_10-80-55-8.remmina +++ /dev/null @@ -1,92 +0,0 @@ -[remmina] -password=. -gateway_username= -notes_text= -vc= -preferipv6=0 -ssh_tunnel_loopback=0 -serialname= -sound=off -printer_overrides= -name=Quick Connect -console=0 -colordepth=99 -security= -precommand= -disable_fastpath=0 -left-handed=0 -postcommand= -multitransport=0 -group= -server=10.80.55.8 -ssh_tunnel_certfile= -glyph-cache=0 -ssh_tunnel_enabled=0 -disableclipboard=0 -audio-output= -parallelpath= -monitorids= -cert_ignore=0 -gateway_server= -serialpermissive=0 -protocol=RDP -old-license=0 -ssh_tunnel_password= -resolution_mode=2 -pth= -loadbalanceinfo= -disableautoreconnect=0 -clientname= -clientbuild= -resolution_width=0 -drive= -relax-order-checks=0 -username=pi -base-cred-for-gw=0 -gateway_domain= -network=none -rdp2tcp= -gateway_password= -serialdriver= -domain= -profile-lock=0 -rdp_reconnect_attempts= -restricted-admin=0 -multimon=0 -exec= -smartcardname= -serialpath= -enable-autostart=0 -usb= -shareprinter=0 -ssh_tunnel_passphrase= -shareparallel=0 -disablepasswordstoring=0 -quality=0 -span=0 -parallelname= -ssh_tunnel_auth=0 -keymap= -ssh_tunnel_username= -execpath= -shareserial=0 -resolution_height=0 -timeout= -useproxyenv=0 -sharesmartcard=0 -freerdp_log_filters= -microphone= -dvc= -ssh_tunnel_privatekey= -gwtransp=http -ssh_tunnel_server= -ignore-tls-errors=1 -disable-smooth-scrolling=0 -gateway_usage=0 -websockets=0 -freerdp_log_level=INFO -window_height=480 -window_maximize=1 -window_width=640 -scale=2 -viewmode=1 diff --git a/configs/remmina_/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina b/configs/remmina_/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina deleted file mode 100644 index 4a49d94..0000000 --- a/configs/remmina_/hosts/group_vnc_edge-004-kansas-us-na-as204466-va3zza-com_193-148-251-11-5900.remmina +++ /dev/null @@ -1,38 +0,0 @@ -[remmina] -encodings= -ssh_tunnel_privatekey= -name=edge-004-kansas-us.na.as204466.va3zza.com -colordepth=32 -password=. -quality=2 -disablesmoothscrolling=0 -precommand= -ssh_tunnel_enabled=0 -viewonly=0 -disableserverinput=0 -ignore-tls-errors=1 -postcommand= -tightencoding=0 -server=193.148.251.11:5900 -disablepasswordstoring=0 -ssh_tunnel_username= -disableclipboard=0 -disableserverbell=0 -ssh_tunnel_password= -profile-lock=0 -showcursor=0 -enable-autostart=0 -disableencryption=0 -ssh_tunnel_loopback=0 -group= -notes_text= -ssh_tunnel_server= -ssh_tunnel_certfile= -keymap= -ssh_tunnel_auth=0 -proxy= -protocol=VNC -username=root@pam -ssh_tunnel_passphrase= -viewmode=1 -window_maximize=0 diff --git a/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina b/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina deleted file mode 100644 index d152f72..0000000 --- a/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-125_ib-8700k-125-industrialbrothers-com.remmina +++ /dev/null @@ -1,69 +0,0 @@ -[remmina] -password= -gateway_username= -ssh_tunnel_loopback=0 -serialname= -printer_overrides= -name=ib-8700k-125 -console=0 -colordepth=64 -security= -precommand= -disable_fastpath=0 -postcommand= -group=IndustrialBrothers -server=ib-8700k-125.industrialbrothers.com -glyph-cache=0 -ssh_tunnel_enabled=0 -disableclipboard=0 -parallelpath= -cert_ignore=0 -gateway_server= -serialpermissive=0 -protocol=RDP -old-license=0 -ssh_tunnel_password= -resolution_mode=2 -disableautoreconnect=0 -loadbalanceinfo= -clientname= -clientbuild= -resolution_width=0 -relax-order-checks=0 -username=epratten -gateway_domain= -serialdriver= -domain= -gateway_password= -smartcardname= -serialpath= -exec= -enable-autostart=0 -shareprinter=0 -ssh_tunnel_passphrase= -disablepasswordstoring=0 -quality=0 -shareparallel=0 -parallelname= -execpath= -shareserial=0 -sharefolder= -sharesmartcard=0 -ssh_tunnel_username= -resolution_height=0 -useproxyenv=0 -microphone= -gwtransp=http -ssh_tunnel_privatekey= -ssh_tunnel_server= -ignore-tls-errors=1 -gateway_usage=0 -ssh_tunnel_auth=2 -sound=off -window_height=525 -last_success=20210825 -window_maximize=1 -window_width=839 -scale=2 -viewmode=1 -keyboard_grab=0 diff --git a/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina b/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina deleted file mode 100644 index 9828a1e..0000000 --- a/configs/remmina_/hosts/industrialbrothers_rdp_ib-8700k-139_ib-8700k-139-industrialbrothers-com.remmina +++ /dev/null @@ -1,69 +0,0 @@ -[remmina] -password=. -gateway_username= -window_height=525 -scale=2 -ssh_tunnel_loopback=0 -serialname= -printer_overrides= -name=ib-8700k-139 -console=0 -colordepth=64 -security= -precommand= -disable_fastpath=0 -postcommand= -group=IndustrialBrothers -server=ib-8700k-139.industrialbrothers.com -glyph-cache=0 -ssh_tunnel_enabled=0 -disableclipboard=0 -parallelpath= -cert_ignore=0 -gateway_server= -serialpermissive=0 -protocol=RDP -ssh_tunnel_password= -old-license=0 -resolution_mode=2 -disableautoreconnect=0 -loadbalanceinfo= -clientname= -clientbuild= -resolution_width=0 -relax-order-checks=0 -username=epratten -gateway_domain= -serialdriver= -domain= -gateway_password= -smartcardname= -exec= -serialpath= -last_success=20220222 -enable-autostart=0 -shareprinter=0 -shareparallel=0 -ssh_tunnel_passphrase= -quality=0 -disablepasswordstoring=0 -parallelname= -viewmode=1 -ssh_tunnel_auth=2 -shareserial=0 -sharefolder= -execpath= -sharesmartcard=0 -ssh_tunnel_username= -resolution_height=0 -useproxyenv=0 -microphone= -keyboard_grab=0 -gwtransp=http -ssh_tunnel_privatekey= -ssh_tunnel_server= -ignore-tls-errors=1 -window_maximize=1 -gateway_usage=0 -window_width=839 -sound=off diff --git a/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina b/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina deleted file mode 100644 index c63432f..0000000 --- a/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5-6001.remmina +++ /dev/null @@ -1,73 +0,0 @@ -[remmina] -password=. -gateway_username= -window_height=525 -ssh_tunnel_loopback=0 -serialname= -printer_overrides= -name=Quick Connect -console=0 -colordepth=8 -security= -precommand= -disable_fastpath=0 -postcommand= -group=VPN Devices -server=10.9.0.5:6001 -viewonly=0 -glyph-cache=0 -ssh_tunnel_enabled=0 -disableclipboard=0 -parallelpath= -cert_ignore=0 -serialpermissive=0 -gateway_server= -protocol=VNC -ssh_tunnel_password= -old-license=0 -resolution_mode=2 -disableautoreconnect=0 -loadbalanceinfo= -clientbuild= -clientname= -resolution_width=0 -relax-order-checks=0 -username=pi -gateway_domain= -showcursor=0 -gateway_password= -serialdriver= -domain= -smartcardname= -exec= -serialpath= -disableserverinput=0 -last_success=20211207 -enable-autostart=0 -shareprinter=0 -shareparallel=0 -ssh_tunnel_passphrase= -proxy= -quality=0 -disablepasswordstoring=0 -parallelname= -viewmode=1 -ssh_tunnel_auth=2 -shareserial=0 -ssh_tunnel_username= -sharesmartcard=0 -sharefolder= -execpath= -resolution_height=0 -useproxyenv=0 -microphone=0 -keymap= -gwtransp=http -ssh_tunnel_privatekey= -ssh_tunnel_server= -ignore-tls-errors=1 -window_maximize=1 -gateway_usage=0 -disableencryption=0 -window_width=640 -sound=off diff --git a/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina b/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina deleted file mode 100644 index cde7012..0000000 --- a/configs/remmina_/hosts/vpn-devices_vnc_quick-connect_10-9-0-5.remmina +++ /dev/null @@ -1,73 +0,0 @@ -[remmina] -password= -gateway_username= -window_height=525 -ssh_tunnel_loopback=0 -serialname= -printer_overrides= -name=Quick Connect -console=0 -colordepth=8 -security= -precommand= -disable_fastpath=0 -postcommand= -group=VPN Devices -server=10.9.0.5 -viewonly=0 -glyph-cache=0 -ssh_tunnel_enabled=0 -disableclipboard=0 -parallelpath= -cert_ignore=0 -serialpermissive=0 -gateway_server= -protocol=VNC -ssh_tunnel_password= -old-license=0 -resolution_mode=2 -disableautoreconnect=0 -loadbalanceinfo= -clientbuild= -clientname= -resolution_width=0 -relax-order-checks=0 -username=pi -gateway_domain= -showcursor=0 -gateway_password= -serialdriver= -domain= -smartcardname= -exec= -serialpath= -disableserverinput=0 -last_success=20211207 -enable-autostart=0 -shareprinter=0 -shareparallel=0 -ssh_tunnel_passphrase= -proxy= -quality=0 -disablepasswordstoring=0 -parallelname= -viewmode=1 -ssh_tunnel_auth=2 -shareserial=0 -ssh_tunnel_username= -sharesmartcard=0 -sharefolder= -execpath= -resolution_height=0 -useproxyenv=0 -microphone=0 -keymap= -gwtransp=http -ssh_tunnel_privatekey= -ssh_tunnel_server= -ignore-tls-errors=1 -window_maximize=1 -gateway_usage=0 -disableencryption=0 -window_width=640 -sound=off From b2760d440ed52bd82c8f2894342ac24d85a2f418 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 4 Oct 2022 22:20:57 -0400 Subject: [PATCH 029/326] gi --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef07850 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/configs/remmina \ No newline at end of file From 85ad686f44f01d7253d1d5cf20893e5a944b9c76 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 4 Oct 2022 22:21:13 -0400 Subject: [PATCH 030/326] nr --- install.conf.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.conf.yaml b/install.conf.yaml index fc190ac..4b0929f 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -16,7 +16,7 @@ path: configs/zsh/.zshrc force: true ~/.config/tabset: configs/tabset - ~/.local/share/remmina: configs/remmina/hosts + # ~/.local/share/remmina: configs/remmina/hosts ~/.config/nvim: configs/nvim ~/bin/catto: path: configs/scripts/catto From 675aec35e76356db79d98d2de92eb0d6f9c32fe5 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 11 Oct 2022 16:21:27 -0400 Subject: [PATCH 031/326] customize nvim a bit --- configs/nvim/init.vim | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index d726d20..3edaf2d 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -43,6 +43,7 @@ Plug 'tpope/vim-surround' Plug 'jiangmiao/auto-pairs' Plug 'airblade/vim-gitgutter' Plug 'nathanaelkane/vim-indent-guides' +Plug 'ggandor/leap.nvim' " And this is where the plugins no longer be call plug#end() @@ -60,4 +61,14 @@ let g:indent_guides_enable_on_vim_startup = 0 let g:indent_guides_guide_size = 1 let g:indent_guides_auto_colors = 0 hi IndentGuidesOdd ctermbg=darkgrey -hi IndentGuidesEven ctermbg=lightgrey \ No newline at end of file +hi IndentGuidesEven ctermbg=lightgrey + +" Enable leap for jumping +lua require('leap').add_default_mappings() + +" Make the gitgutter look cleaner +let g:gitgutter_override_sign_column_highlight = 0 +highlight clear SignColumn +highlight GitGutterAdd guifg=#009900 ctermfg=2 +highlight GitGutterChange guifg=#bbbb00 ctermfg=3 +highlight GitGutterDelete guifg=#ff2222 ctermfg=1 From 3f22aebdbc514afcf7a3c9557f75632a8f44f8a8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 11 Oct 2022 16:36:39 -0400 Subject: [PATCH 032/326] Add desync warnings --- configs/nvim/init.vim | 3 +++ configs/zsh/info.sh | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 3edaf2d..1eba75c 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -20,6 +20,9 @@ vnoremap + " Force VIM to use system clipboard set clipboard=unnamedplus diff --git a/configs/zsh/info.sh b/configs/zsh/info.sh index 53076b8..8522ddd 100644 --- a/configs/zsh/info.sh +++ b/configs/zsh/info.sh @@ -1,2 +1,18 @@ echo "$fg[$HOST_COLOR]Platform:$reset_color $(uname -o) $(uname -r)" -echo "$fg[$HOST_COLOR]Uptime:$reset_color $(uptime -p)" \ No newline at end of file +echo "$fg[$HOST_COLOR]Uptime:$reset_color $(uptime -p)" + +# Determine if $EWCONFIG_ROOT contains uncommitted changes +if [ -d $EWCONFIG_ROOT/.git ]; then + if [ -n "$(git -C $EWCONFIG_ROOT status --porcelain)" ]; then + echo "$fg[red]ewconfig contains uncommitted changes$reset_color" + fi +fi + +# Determine if $EWCONFIG_ROOT is up-to-date with origin. Only do this if we have network connectivity. +if [ -d $EWCONFIG_ROOT/.git ]; then + if ping -c 1 -W 1 git.github.com &> /dev/null; then + if [ -n "$(git -C $EWCONFIG_ROOT fetch --dry-run 2>&1 | grep -v 'up to date')" ]; then + echo "$fg[yellow]ewconfig is not up-to-date with origin$reset_color" + fi + fi +fi \ No newline at end of file From b292a1bb084a835de0566f61136b2879d77e922a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 11 Oct 2022 16:37:09 -0400 Subject: [PATCH 033/326] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d26b161..262f06b 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,4 @@ And in `nvim`, run :PlugInstall :Copilot setup ``` + From 184f04cecf02709e43cf8778571d4724d4790da0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Oct 2022 18:07:18 -0400 Subject: [PATCH 034/326] ASPATH script --- configs/scripts/aspath | 26 ++++++++++++++++++++++++++ configs/zsh/macros.sh | 22 ++++++++++++++++++++++ install.conf.yaml | 6 +++++- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100755 configs/scripts/aspath diff --git a/configs/scripts/aspath b/configs/scripts/aspath new file mode 100755 index 0000000..59d3467 --- /dev/null +++ b/configs/scripts/aspath @@ -0,0 +1,26 @@ +#! /bin/bash +set -e + +# Ensure we were passed a host argument +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +# Parse out the ASNs +asns=$( mtr -jzc1 $1 | jq ".report.hubs[].ASN" | tr -d "\"" | uniq ) + +# For each line +for asn in $asns; do + # Skip "AS???" lines + if [[ $asn =~ ^AS\?\?\?$ ]]; then + echo "Private Hop" + continue + fi + + # Get the AS name + as_name=$( whois -h whois.radb.net $asn | grep -i ^descr: | cut -d : -f 2- | grep -o -E '\S.*\S|\S' ) + + # Print the ASN and AS name + echo "$asn - $as_name" +done \ No newline at end of file diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index ea8f9e2..29e5f32 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -8,6 +8,28 @@ alias p4='ping 8.8.8.8 -c 4' alias quickhttp='sudo python -m SimpleHTTPServer 443' alias zshreload="source ~/.zshrc" alias wg-easykeys="wg genkey | tee >(wg pubkey)" +alias nvim-tmp="nvim $(mktemp)" + +# WHOIS macros +alias whois-afrinic="whois -h whois.afrinic.net" +alias whois-altdb="whois -h whois.altdb.net" +alias whois-aoltw="whois -h whois.aoltw.net" +alias whois-ampr="whois -h whois.ampr.org" +alias whois-apnic="whois -h whois.apnic.net" +alias whois-arin="whois -h rr.arin.net" +alias whois-bell="whois -h whois.in.bell.ca" +alias whois-bboi="whois -h irr.bboi.net" +alias whois-bgptools="whois -h bgp.tools" +alias whois-canarie="whois -h whois.canarie.ca" +alias whois-epoch="whois -h whois.epoch.net" +alias whois-jpirr="whois -h jpirr.nic.ad.jp" +alias whois-lacnic="whois -h irr.lacnic.net" +alias whois-level3="whois -h rr.level3.net" +alias whois-nestegg="whois -h whois.nestegg.net" +alias whois-panix="whois -h rrdb.access.net" +alias whois-radb="whois -h whois.radb.net" +alias whois-reach="whois -h rr.telstraglobal.net" +alias whois-ripe="whois -h whois.ripe.net" # Kill via pgrep nkill() { diff --git a/install.conf.yaml b/install.conf.yaml index 4b0929f..a869c5f 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -21,7 +21,11 @@ ~/bin/catto: path: configs/scripts/catto mode: 755 + ~/bin/aspath: + path: configs/scripts/aspath + mode: 755 - shell: - [git submodule update --init --recursive, Installing submodules] - - [chmod +x configs/scripts/catto, Making catto executable] \ No newline at end of file + - [chmod +x configs/scripts/catto, Making catto executable] + - [chmod +x configs/scripts/aspath, Making aspath executable] \ No newline at end of file From 54b30fb6146bf2431157e7be6715d93378db6e8f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 14 Nov 2022 20:33:43 -0500 Subject: [PATCH 035/326] dns macro --- configs/zsh/macros.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 29e5f32..2485da9 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -4,11 +4,10 @@ alias la="ls -a" alias :q="exit" alias :wq="exit" alias cls=clear -alias p4='ping 8.8.8.8 -c 4' -alias quickhttp='sudo python -m SimpleHTTPServer 443' alias zshreload="source ~/.zshrc" alias wg-easykeys="wg genkey | tee >(wg pubkey)" alias nvim-tmp="nvim $(mktemp)" +alias flush-dns="sudo systemd-resolve --flush-caches" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" @@ -33,7 +32,11 @@ alias whois-ripe="whois -h whois.ripe.net" # Kill via pgrep nkill() { - kill -9 $(pgrep $1) + if [ $# != 1 ]; then + echo "Usage: nkill " + else + kill -9 $(pgrep $1) + fi } # Makes a directory, then moves into it From 3babdcb7199fd4ffa2493a5959f12505d4ed2ce6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 19 Nov 2022 10:14:45 -0500 Subject: [PATCH 036/326] Auto-configure GNOME if possible --- configs/gnome/desktop-settings.sh | 46 +++++++++++++++++++++++++++ configs/gnome/terminal/terminal.dconf | 7 ++++ configs/nvim/init.vim | 6 ++-- helpers/configure-gnome.sh | 16 ++++++++++ install.conf.yaml | 3 +- 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 configs/gnome/desktop-settings.sh create mode 100644 configs/gnome/terminal/terminal.dconf create mode 100644 helpers/configure-gnome.sh diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh new file mode 100644 index 0000000..7ee8fbf --- /dev/null +++ b/configs/gnome/desktop-settings.sh @@ -0,0 +1,46 @@ +#! /bin/sh +# This script configures GNOME to my liking +set -e + +# Require gsettings +if ! command -v gsettings >/dev/null 2>&1; then + echo "gsettings is not installed, skipping some GNOME configuration" + exit 0 +fi + +# Mouse settings +gsettings set org.gnome.desktop.interface gtk-enable-primary-paste true # Middle click paste +gsettings set org.gnome.desktop.peripherals.touchpad disable-while-typing false # Allow touchpad while typing +gsettings set org.gnome.desktop.peripherals.touchpad natural-scroll false # Disable natural scrolling on touchpad + +# Keyboard settings +gsettings set org.gnome.desktop.wm.keybindings close "['q']" # Close windows with Mod+Shift+q +gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-1 "['exclam']" # Move a window to ws 1 +gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-2 "['at']" # Move a window to ws 2 +gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-3 "['numbersign']" # Move a window to ws 3 +gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-4 "['dollar']" # Move a window to ws 4 +gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 "['1']" # Switch to ws 1 +gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-2 "['2']" # Switch to ws 2 +gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-3 "['3']" # Switch to ws 3 +gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['4']" # Switch to ws 4 + +# Allow Mod+Enter to open a terminal +gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name "Open Terminal" +gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ command "gnome-terminal" +gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ binding "Return" + +# Top Bar settings +gsettings set org.gnome.desktop.interface clock-format 24h # 24 hour clock +gsettings set org.gnome.desktop.interface clock-show-date true # Show date in top bar +gsettings set org.gnome.desktop.interface clock-show-weekday true # Show weekday in top bar + +# Window settings +gsettings set org.gnome.desktop.wm.preferences focus-mode 'sloppy' # Focus windows on mouse hover +gsettings set org.gnome.desktop.wm.preferences auto-raise false # Don't auto-raise windows + +# Desktop settings +gsettings set org.gnome.desktop.interface enable-hot-corners false # Disable hot corners +gsettings set org.gnome.mutter edge-tiling true # Enable edge tiling +gsettings set org.gnome.mutter dynamic-workspaces false # Use a fixed number of workspaces +gsettings set org.gnome.desktop.wm.preferences num-workspaces 4 # Use 4 workspaces +gsettings set org.gnome.mutter workspaces-only-on-primary true # Only use workspaces on primary monitor diff --git a/configs/gnome/terminal/terminal.dconf b/configs/gnome/terminal/terminal.dconf new file mode 100644 index 0000000..c563b92 --- /dev/null +++ b/configs/gnome/terminal/terminal.dconf @@ -0,0 +1,7 @@ +[legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9] +custom-command='/usr/bin/zsh' +default-size-columns=100 +default-size-rows=40 +login-shell=true +use-custom-command=true +visible-name='Default' diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 1eba75c..e5034f5 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -40,13 +40,13 @@ endif " This is where the plugins be call plug#begin() -Plug 'github/copilot.vim' +" Plug 'github/copilot.vim' Plug 'tpope/vim-fugitive' Plug 'tpope/vim-surround' Plug 'jiangmiao/auto-pairs' Plug 'airblade/vim-gitgutter' Plug 'nathanaelkane/vim-indent-guides' -Plug 'ggandor/leap.nvim' +" Plug 'ggandor/leap.nvim' " And this is where the plugins no longer be call plug#end() @@ -67,7 +67,7 @@ hi IndentGuidesOdd ctermbg=darkgrey hi IndentGuidesEven ctermbg=lightgrey " Enable leap for jumping -lua require('leap').add_default_mappings() +" lua require('leap').add_default_mappings() " Make the gitgutter look cleaner let g:gitgutter_override_sign_column_highlight = 0 diff --git a/helpers/configure-gnome.sh b/helpers/configure-gnome.sh new file mode 100644 index 0000000..0faa1ff --- /dev/null +++ b/helpers/configure-gnome.sh @@ -0,0 +1,16 @@ +#! /bin/sh +set -e + +# Check if dconf is available +if ! command -v dconf >/dev/null 2>&1; then + echo "dconf is not installed, skipping GNOME configuration" + exit 0 +fi + +# Configure gnome-terminal +echo "Writing gnome-terminal settings..." +dconf load "/org/gnome/terminal/" < configs/gnome/terminal/terminal.dconf + +# Configure GNOME itself +echo "Writing GNOME settings..." +sh ./configs/gnome/desktop-settings.sh \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index a869c5f..1a66dc7 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -28,4 +28,5 @@ - shell: - [git submodule update --init --recursive, Installing submodules] - [chmod +x configs/scripts/catto, Making catto executable] - - [chmod +x configs/scripts/aspath, Making aspath executable] \ No newline at end of file + - [chmod +x configs/scripts/aspath, Making aspath executable] + - [sh ./helpers/configure-gnome.sh, Configuring GNOME] \ No newline at end of file From 5edbc5347f8e1ae2d23d48a8eaa742926705cf05 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 19 Nov 2022 10:15:41 -0500 Subject: [PATCH 037/326] Speed up shell launch --- configs/zsh/info.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/configs/zsh/info.sh b/configs/zsh/info.sh index 8522ddd..2a9c182 100644 --- a/configs/zsh/info.sh +++ b/configs/zsh/info.sh @@ -8,11 +8,11 @@ if [ -d $EWCONFIG_ROOT/.git ]; then fi fi -# Determine if $EWCONFIG_ROOT is up-to-date with origin. Only do this if we have network connectivity. -if [ -d $EWCONFIG_ROOT/.git ]; then - if ping -c 1 -W 1 git.github.com &> /dev/null; then - if [ -n "$(git -C $EWCONFIG_ROOT fetch --dry-run 2>&1 | grep -v 'up to date')" ]; then - echo "$fg[yellow]ewconfig is not up-to-date with origin$reset_color" - fi - fi -fi \ No newline at end of file +# # Determine if $EWCONFIG_ROOT is up-to-date with origin. Only do this if we have network connectivity. +# if [ -d $EWCONFIG_ROOT/.git ]; then +# if ping -c 1 -W 1 git.github.com &> /dev/null; then +# if [ -n "$(git -C $EWCONFIG_ROOT fetch --dry-run 2>&1 | grep -v 'up to date')" ]; then +# echo "$fg[yellow]ewconfig is not up-to-date with origin$reset_color" +# fi +# fi +# fi \ No newline at end of file From afde61da7d5475edfab3b6b1e1b6aacf14fd948d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 19 Nov 2022 12:41:29 -0500 Subject: [PATCH 038/326] Disable app switch hotkeys --- configs/gnome/desktop-settings.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index 7ee8fbf..94318dc 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -12,6 +12,19 @@ fi gsettings set org.gnome.desktop.interface gtk-enable-primary-paste true # Middle click paste gsettings set org.gnome.desktop.peripherals.touchpad disable-while-typing false # Allow touchpad while typing gsettings set org.gnome.desktop.peripherals.touchpad natural-scroll false # Disable natural scrolling on touchpad +gsettings set org.gnome.desktop.peripherals.touchpad tap-to-click true # Enable tap-to-click on touchpad +gsettings set org.gnome.desktop.interface show-battery-percentage true # Show battery percentage + +# Disable application switching with Super+num keyy +gsettings set org.gnome.shell.keybindings switch-to-application-1 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-2 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-3 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-4 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-5 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-6 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-7 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-8 "[]" +gsettings set org.gnome.shell.keybindings switch-to-application-9 "[]" # Keyboard settings gsettings set org.gnome.desktop.wm.keybindings close "['q']" # Close windows with Mod+Shift+q From 8f2c14a2eb3ba89fdf487b73aba2c8c8b217f064 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 19 Nov 2022 12:46:27 -0500 Subject: [PATCH 039/326] one-time gnome-terminal keybind --- configs/gnome/desktop-settings.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index 94318dc..dd93a4c 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -38,9 +38,13 @@ gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-3 "['3 gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['4']" # Switch to ws 4 # Allow Mod+Enter to open a terminal -gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name "Open Terminal" -gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ command "gnome-terminal" -gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ binding "Return" +keybindings=$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings) +if [ "$keybindings" = "[]" ]; then + gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name "Terminal" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ command "gnome-terminal" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ binding "Return" +fi # Top Bar settings gsettings set org.gnome.desktop.interface clock-format 24h # 24 hour clock From c648e76845dc4eae8cc01d791aabb1b75263905e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 19 Nov 2022 12:47:38 -0500 Subject: [PATCH 040/326] logic fix --- configs/gnome/desktop-settings.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index dd93a4c..fc1bdc8 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -39,7 +39,7 @@ gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['4 # Allow Mod+Enter to open a terminal keybindings=$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings) -if [ "$keybindings" = "[]" ]; then +if [ "$keybindings" = "[]" || "$keybindings" = "@as []" ]; then gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name "Terminal" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ command "gnome-terminal" From 3b5214ff0fdc5812c2b1faa9599f2b526d5714e4 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 19 Nov 2022 12:48:45 -0500 Subject: [PATCH 041/326] I'm bad at syntax --- configs/gnome/desktop-settings.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index fc1bdc8..bd30696 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -39,7 +39,7 @@ gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['4 # Allow Mod+Enter to open a terminal keybindings=$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings) -if [ "$keybindings" = "[]" || "$keybindings" = "@as []" ]; then +if [ "$keybindings" = "[]" ] || [ "$keybindings" = "@as []" ]; then gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name "Terminal" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ command "gnome-terminal" From 1f7cef1d17c90c8b1e86edcbe7c490910b769d37 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 7 Dec 2022 14:23:37 -0500 Subject: [PATCH 042/326] du macro --- configs/zsh/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 2485da9..b172e61 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -8,6 +8,7 @@ alias zshreload="source ~/.zshrc" alias wg-easykeys="wg genkey | tee >(wg pubkey)" alias nvim-tmp="nvim $(mktemp)" alias flush-dns="sudo systemd-resolve --flush-caches" +alias showsizes="du -h --max-depth=1" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From 55e7b46794ed9f9a5434efc241279bae7068515a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 11 Dec 2022 11:50:37 -0500 Subject: [PATCH 043/326] Set up ssh config linking --- configs/ssh/config | 63 +++++++++++++++++++---------------- helpers/install-ssh-config.sh | 13 ++++++++ install.conf.yaml | 1 + 3 files changed, 48 insertions(+), 29 deletions(-) create mode 100644 helpers/install-ssh-config.sh diff --git a/configs/ssh/config b/configs/ssh/config index 79a237f..a15db02 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -1,26 +1,3 @@ -# Personal servers -Host rtl-netlink - HostName netlink.local - User pi - -Host rtl-compute - Hostname compute.local - User pi - -Host gw-ca-tor-01 - Hostname gw-ca-tor-01.servers.retrylife.ca - -Host hp-desktop - Hostname 10.9.0.12 - -Host ewpratten-laptop - Hostname 10.9.0.2 - User ewpratten - -Host ewpratten-desktop - Hostname 10.9.0.9 - User ewpratten - # Github SSH adapter for restricted networks Host github.com HostName ssh.github.com @@ -28,9 +5,26 @@ Host github.com Host gist.github.com HostName ssh.github.com - Port 443 + Port 443 -# IndustrialBrothers Internal network +# Home network +Host unifi + HostName Dream-Machine-Pro.local + User root + PubkeyAcceptedKeyTypes +ssh-rsa + HostKeyAlgorithms +ssh-rsa + +Host ewpratten-steamdeck + HostName ewpratten-steamdeck.local + User deck + ForwardX11 yes + +Host mc.homieho.me + User root + PreferredAuthentications password + PubkeyAuthentication no + +# IndustrialBrothers domain Host ib-* Hostname %h.industrialbrothers.com IdentityFile ~/.ssh/industrialbrothers_id_ed25519 @@ -38,7 +32,8 @@ Host ib-* User epratten Host *.industrialbrothers.com - IdentityFile ~/.ssh/industrialbrothers_id_ed25519 + IdentityFile ~/.ssh/industrialbrothers_id_ed25519 + User epratten Host ib-8700k-125 RemoteCommand powershell "& 'C:\Program Files\Git\bin\sh.exe' --login" @@ -48,9 +43,6 @@ Host ib-8700k-139 Host ib-rfcpu-002-lnx User evan -Host ib-rfcpu-001-lnx - User epratten - # Default hostnames I may encounter in the wild Host openrepeater.local HostName openrepeater.local @@ -75,4 +67,17 @@ Host atlas Host sheridan-cpanel User prattene HostName cpanel.prattene.dev.fast.sheridanc.on.ca + PubkeyAcceptedKeyTypes +ssh-rsa + HostKeyAlgorithms=+ssh-rsa +# NLNOG +Host *.ring.nlnog.net + User ewpratten + IdentitiesOnly yes + #IdentityFile ~/.ssh/id_ed25519_sk_rk.pub + +# SDF.org +Host *.sdf.org + user ewpratten + PreferredAuthentications password + PubkeyAuthentication no \ No newline at end of file diff --git a/helpers/install-ssh-config.sh b/helpers/install-ssh-config.sh new file mode 100644 index 0000000..ef1ed14 --- /dev/null +++ b/helpers/install-ssh-config.sh @@ -0,0 +1,13 @@ +#! /bin/sh +# Installs the SSH config file +set -e + +# Link the SSH config file +echo "Linking SSH config file..." +mkdir -p "$HOME/.ssh" +ln -sf "$(pwd)/configs/ssh/config" "$HOME/.ssh/config" + +# Set the correct permissions +echo "Setting SSH config file permissions..." +chmod 644 "$HOME/.ssh/config" +chown "$USER:$USER" "$HOME/.ssh/config" \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index 1a66dc7..d795d26 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -27,6 +27,7 @@ - shell: - [git submodule update --init --recursive, Installing submodules] + - [sh ./helpers/install-ssh-config.sh, Installing SSH config] - [chmod +x configs/scripts/catto, Making catto executable] - [chmod +x configs/scripts/aspath, Making aspath executable] - [sh ./helpers/configure-gnome.sh, Configuring GNOME] \ No newline at end of file From 29ea2be573652c63ab41ae71e79e290327e3e273 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 11 Dec 2022 11:52:05 -0500 Subject: [PATCH 044/326] always try to load sdkman --- configs/zsh/.zshrc | 4 ++++ configs/zsh/by_host/ewpratten-desktop.sh | 5 ----- 2 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 configs/zsh/by_host/ewpratten-desktop.sh diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 940a6b0..7752537 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -18,3 +18,7 @@ fi # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" + +# SDKMAN! +export SDKMAN_DIR="$HOME/.sdkman" +[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" \ No newline at end of file diff --git a/configs/zsh/by_host/ewpratten-desktop.sh b/configs/zsh/by_host/ewpratten-desktop.sh deleted file mode 100644 index ea06869..0000000 --- a/configs/zsh/by_host/ewpratten-desktop.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /bin/bash - -# SDKMAN! -export SDKMAN_DIR="$HOME/.sdkman" -[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" From c81ecca7801cd586af59349a9c5e61080534faac Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 11 Dec 2022 11:56:29 -0500 Subject: [PATCH 045/326] sdf org --- configs/ssh/config | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configs/ssh/config b/configs/ssh/config index a15db02..2f36116 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -80,4 +80,9 @@ Host *.ring.nlnog.net Host *.sdf.org user ewpratten PreferredAuthentications password - PubkeyAuthentication no \ No newline at end of file + PubkeyAuthentication no + +Host sdf.org + user ewpratten + PreferredAuthentications password + PubkeyAuthentication no From fd874d923f774139f8a5f598ef01850dbbc904ca Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 21 Dec 2022 15:53:05 -0500 Subject: [PATCH 046/326] conf --- configs/ssh/config | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index 2f36116..684baa7 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -9,10 +9,10 @@ Host gist.github.com # Home network Host unifi - HostName Dream-Machine-Pro.local - User root - PubkeyAcceptedKeyTypes +ssh-rsa - HostKeyAlgorithms +ssh-rsa + HostName DreamMachinePro.local + User root + PreferredAuthentications password + PubkeyAuthentication no Host ewpratten-steamdeck HostName ewpratten-steamdeck.local From 820af097843bb9ba5fe2190879fef70e8813bfa0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Jan 2023 11:10:36 -0500 Subject: [PATCH 047/326] add lsgrep --- configs/zsh/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index b172e61..3969e84 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -9,6 +9,7 @@ alias wg-easykeys="wg genkey | tee >(wg pubkey)" alias nvim-tmp="nvim $(mktemp)" alias flush-dns="sudo systemd-resolve --flush-caches" alias showsizes="du -h --max-depth=1" +alias lsgrep="ls | grep" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From 717fae080806238c6a9a2c83bc0093418de1c776 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Jan 2023 12:15:29 -0500 Subject: [PATCH 048/326] neo-aliases --- configs/zsh/macros.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 3969e84..c4d0acf 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -32,6 +32,10 @@ alias whois-radb="whois -h whois.radb.net" alias whois-reach="whois -h rr.telstraglobal.net" alias whois-ripe="whois -h whois.ripe.net" +# Neo-aliases +if [ -x "$(command -v nvim)" ]; then alias vim="nvim"; fi +if [ -x "$(command -v neomutt)" ]; then alias mutt="neomutt"; fi + # Kill via pgrep nkill() { if [ $# != 1 ]; then From d2a4d3522f8ef42f0fed13f3be78d6e0d1dd1500 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 10 Feb 2023 10:29:24 -0500 Subject: [PATCH 049/326] added stuff --- configs/zsh/.zshrc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 7752537..e6e4433 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -18,7 +18,9 @@ fi # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" +export PATH="$HOME/.local/bin:$PATH" # SDKMAN! export SDKMAN_DIR="$HOME/.sdkman" -[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" \ No newline at end of file +[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" + From eef703140ef17b13e5f204eddd4348e4d3137a30 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 10 Feb 2023 10:31:57 -0500 Subject: [PATCH 050/326] ssh config --- configs/ssh/config | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index 684baa7..72c8db8 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -24,6 +24,13 @@ Host mc.homieho.me PreferredAuthentications password PubkeyAuthentication no +Host 10.80.0.218 + User root + PreferredAuthentications password + PubkeyAuthentication no + PubkeyAcceptedKeyTypes +ssh-rsa + HostKeyAlgorithms=+ssh-rsa + # IndustrialBrothers domain Host ib-* Hostname %h.industrialbrothers.com @@ -51,7 +58,14 @@ Host openrepeater.local Host raspberrypi.local StrictHostKeyChecking no - User pi + User pi + +Host 192.168.8.1 + User root + PreferredAuthentications password + PubkeyAuthentication no + PubkeyAcceptedKeyTypes +ssh-rsa + HostKeyAlgorithms=+ssh-rsa # Raider Robotics Host 10.50.24.2 @@ -62,7 +76,7 @@ Host 10.50.24.2 Host atlas User prattene RequestTTY yes - RemoteCommand ~/.local/bin/zsh --login + # RemoteCommand ~/.local/bin/zsh --login Host sheridan-cpanel User prattene @@ -86,3 +100,8 @@ Host sdf.org user ewpratten PreferredAuthentications password PubkeyAuthentication no + +# Personal Infra +Host oci-arm + HostName oci-arm.ip.ewp.fyi + User ubuntu From 4a91d11ffbbc957a3abdf51b3dc1056cce146618 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 16 Feb 2023 13:16:14 -0500 Subject: [PATCH 051/326] steamdeck screenshot fetcher --- configs/scripts/fetch-steamdeck-screenshots | 38 +++++++++++++++++++++ install.conf.yaml | 4 +++ 2 files changed, 42 insertions(+) create mode 100755 configs/scripts/fetch-steamdeck-screenshots diff --git a/configs/scripts/fetch-steamdeck-screenshots b/configs/scripts/fetch-steamdeck-screenshots new file mode 100755 index 0000000..2e758e7 --- /dev/null +++ b/configs/scripts/fetch-steamdeck-screenshots @@ -0,0 +1,38 @@ +#! /bin/bash +set -e + +# If no arguments are given, print usage and exit +if [ $# -eq 0 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Prepare the script to run on the remote host +cat < /tmp/steamdeck-screenshot.sh +#!/bin/bash +set -e + +# Clean the screenshots directory +rm -rf /tmp/screenshot-bundle || true +mkdir -p /tmp/screenshot-bundle + +# Copy all screenshots to the bundle directory +IMAGES=\$(find /home/deck/.local/share/Steam/userdata | grep "screenshots/[0-9]") +for pathname in \$IMAGES; do + echo "Copying \$pathname" + cp --preserve=timestamps "\$pathname" /tmp/screenshot-bundle +done + +# Compress the bundle directory +tar -czf /tmp/screenshot-bundle.tar.gz /tmp/screenshot-bundle +EOF + +# Copy the script to the remote host +scp /tmp/steamdeck-screenshot.sh $1:/tmp/steamdeck-screenshot.sh + +# Run the script on the remote host +ssh $1 bash /tmp/steamdeck-screenshot.sh + +# Copy the bundle from the remote host +TIMESTAMP=$(date +%Y%m%d-%H%M%S) +scp $1:/tmp/screenshot-bundle.tar.gz ~/Downloads/steamdeck_screenshots_${TIMESTMAP}.tar.gz \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index d795d26..bb59093 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -24,10 +24,14 @@ ~/bin/aspath: path: configs/scripts/aspath mode: 755 + ~/bin/fetch-steamdeck-screenshots: + path: configs/scripts/fetch-steamdeck-screenshots + mode: 755 - shell: - [git submodule update --init --recursive, Installing submodules] - [sh ./helpers/install-ssh-config.sh, Installing SSH config] - [chmod +x configs/scripts/catto, Making catto executable] - [chmod +x configs/scripts/aspath, Making aspath executable] + - [chmod +x configs/scripts/fetch-steamdeck-screenshots, Making fetch-steamdeck-screenshots executable] - [sh ./helpers/configure-gnome.sh, Configuring GNOME] \ No newline at end of file From abd2be6aec0a462abda62e30c4538990c24d3aaf Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 8 Mar 2023 12:18:05 -0500 Subject: [PATCH 052/326] cli macro for sheridan rdp --- configs/zsh/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index c4d0acf..5ffbf66 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -10,6 +10,7 @@ alias nvim-tmp="nvim $(mktemp)" alias flush-dns="sudo systemd-resolve --flush-caches" alias showsizes="du -h --max-depth=1" alias lsgrep="ls | grep" +alias sheridan-rdp='firefox --new-window "ext+container:name=College&url=https://client.wvd.microsoft.com/arm/webclient/index.html"' # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From e47ff45a51cbf8841a8d20643c9f2c6a4ff13cca Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Mar 2023 15:50:22 -0400 Subject: [PATCH 053/326] remove leap --- configs/nvim/init.vim | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index e5034f5..d47bc7e 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -46,7 +46,6 @@ Plug 'tpope/vim-surround' Plug 'jiangmiao/auto-pairs' Plug 'airblade/vim-gitgutter' Plug 'nathanaelkane/vim-indent-guides' -" Plug 'ggandor/leap.nvim' " And this is where the plugins no longer be call plug#end() @@ -66,9 +65,6 @@ let g:indent_guides_auto_colors = 0 hi IndentGuidesOdd ctermbg=darkgrey hi IndentGuidesEven ctermbg=lightgrey -" Enable leap for jumping -" lua require('leap').add_default_mappings() - " Make the gitgutter look cleaner let g:gitgutter_override_sign_column_highlight = 0 highlight clear SignColumn From ec4ac1dc693f199b4c9d42d8205115c1df6ce0c7 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 2 May 2023 14:49:15 -0400 Subject: [PATCH 054/326] www --- install.conf.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install.conf.yaml b/install.conf.yaml index bb59093..d972857 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -9,6 +9,7 @@ - ~/bin - ~/projects - ~/src + - ~/www - link: ~/.gitconfig: configs/git/.gitconfig @@ -34,4 +35,4 @@ - [chmod +x configs/scripts/catto, Making catto executable] - [chmod +x configs/scripts/aspath, Making aspath executable] - [chmod +x configs/scripts/fetch-steamdeck-screenshots, Making fetch-steamdeck-screenshots executable] - - [sh ./helpers/configure-gnome.sh, Configuring GNOME] \ No newline at end of file + - [sh ./helpers/configure-gnome.sh, Configuring GNOME] From 3a88dd1a64b3e7dd432343280b9c97b127a81dda Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 4 May 2023 14:21:10 -0400 Subject: [PATCH 055/326] Copy to web --- configs/nautilus/scripts/Copy to web | 36 ++++++++++++++++++++++++++++ install.conf.yaml | 4 ++++ 2 files changed, 40 insertions(+) create mode 100755 configs/nautilus/scripts/Copy to web diff --git a/configs/nautilus/scripts/Copy to web b/configs/nautilus/scripts/Copy to web new file mode 100755 index 0000000..9207a42 --- /dev/null +++ b/configs/nautilus/scripts/Copy to web @@ -0,0 +1,36 @@ +#! /bin/bash +set -e + +WEBSERVER_PATH=$HOME/www + +# If NAUTILUS_SCRIPT_SELECTED_FILE_PATHS is empty, error and exit +if [ -z "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" ]; then + notify-send "Copy to web" "No local files selected" + exit 1 +fi + +# For every file in NAUTILUS_SCRIPT_SELECTED_FILE_PATHS +echo "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" | while read file; do + # Get the last segment of the path + filename=$(basename "$file") + + # If the file comes from ~/Pictures/Screenshots, use a path in ~/$WEBSERVER_PATH/screenshots + if [[ "$file" == "$HOME/Pictures/Screenshots/"* ]]; then + OUTPUT_PATH="$WEBSERVER_PATH/screenshots/$filename" + RES_PATH="/screenshots/$filename" + mkdir -p "$WEBSERVER_PATH/screenshots" + else + OUTPUT_PATH="$WEBSERVER_PATH/$filename" + RES_PATH="/$filename" + fi + + # Copy the file to the webserver + cp -r "$file" "$OUTPUT_PATH" + + # Write the resource path to the clipbaord + echo -n "$RES_PATH" | xsel -i -b + +done + +# Show a success message +notify-send "Copy to web" "Files copied to ~/www" diff --git a/install.conf.yaml b/install.conf.yaml index d972857..b1f4e65 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -10,6 +10,7 @@ - ~/projects - ~/src - ~/www + - ~/.local/share/nautilus/scripts/ - link: ~/.gitconfig: configs/git/.gitconfig @@ -28,6 +29,9 @@ ~/bin/fetch-steamdeck-screenshots: path: configs/scripts/fetch-steamdeck-screenshots mode: 755 + ~/.local/share/nautilus/scripts/Copy to web: + path: configs/nautilus/scripts/Copy to web + mode: 755 - shell: - [git submodule update --init --recursive, Installing submodules] From 9b9fb1ef963be75bcd7b0d8b12d51925cfa839dc Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 7 May 2023 17:38:08 -0400 Subject: [PATCH 056/326] Add rofi support --- configs/gnome/desktop-settings.sh | 12 ++++++++++-- configs/rofi/config.rasi | 4 ++++ install.conf.yaml | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 configs/rofi/config.rasi diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index bd30696..b1717dd 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -37,13 +37,21 @@ gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-2 "['2 gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-3 "['3']" # Switch to ws 3 gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['4']" # Switch to ws 4 -# Allow Mod+Enter to open a terminal +# Generate custom keybinds if they do not yet exist keybindings=$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings) if [ "$keybindings" = "[]" ] || [ "$keybindings" = "@as []" ]; then - gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']" + # Define the list of custom keybindings + gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/']" + + # Allow Mod+Enter to open a terminal gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name "Terminal" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ command "gnome-terminal" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ binding "Return" + + # Allow Mod+d to launch rofi + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ name "Rofi" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ command "rofi -show drun" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ binding "d" fi # Top Bar settings diff --git a/configs/rofi/config.rasi b/configs/rofi/config.rasi new file mode 100644 index 0000000..4315809 --- /dev/null +++ b/configs/rofi/config.rasi @@ -0,0 +1,4 @@ +configuration { + show-icons: false; +} +@theme "dmenu" \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index b1f4e65..292a763 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -18,6 +18,7 @@ path: configs/zsh/.zshrc force: true ~/.config/tabset: configs/tabset + ~/.config/rofi: configs/rofi # ~/.local/share/remmina: configs/remmina/hosts ~/.config/nvim: configs/nvim ~/bin/catto: From 7848a96b3d8f6ca1e3f5cfa31965a0a77edc1b73 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 21 May 2023 10:15:11 -0400 Subject: [PATCH 057/326] Add flutter support --- configs/zsh/.zshrc | 2 ++ install.conf.yaml | 1 + 2 files changed, 3 insertions(+) diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index e6e4433..15ce3ef 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -24,3 +24,5 @@ export PATH="$HOME/.local/bin:$PATH" export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" +# Flutter +[[ -s "$HOME/pkg/flutter/bin" ]] && export PATH="$HOME/pkg/flutter/bin:$PATH" diff --git a/install.conf.yaml b/install.conf.yaml index 292a763..e98a2eb 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -10,6 +10,7 @@ - ~/projects - ~/src - ~/www + - ~/pkg - ~/.local/share/nautilus/scripts/ - link: From 3f55407ac9a197eaeddc5cec582867895c6d97f2 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 31 May 2023 14:52:39 -0400 Subject: [PATCH 058/326] zstd extract support --- configs/zsh/macros.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 5ffbf66..dc65edd 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -77,6 +77,8 @@ extract() { *.zip) unzip $1 ;; *.Z) uncompress $1 ;; *.7z) 7z x $1 ;; + *.tar.zst) tar --use-compress-program=unzstd -xvf $1 ;; + *.zst) zstd -d $1 ;; *) echo "don't know how to extract '$1'..." ;; esac else From b997c20887816a1f3f1f8e01abadf2852b20c09c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 7 Jun 2023 23:42:25 -0400 Subject: [PATCH 059/326] genpass --- configs/zsh/macros.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index dc65edd..76d2c84 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -85,3 +85,13 @@ extract() { echo "'$1' is not a valid file!" fi } + +# Generate a password +genpass() { + if [ $# != 1 ]; then + echo "Usage: genpass " + else + echo $(openssl rand -base64 $1 | tr -d "\n") + fi + +} From 9d9d9c87fe7ab530b93ffdbdf1b505950c29ec8a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 13 Jun 2023 16:04:44 -0400 Subject: [PATCH 060/326] Improve git defaults --- configs/git/.gitconfig | 21 +++++++++++++++++++++ configs/ssh/allowed_signers | 1 + configs/zsh/.zshrc | 11 +++++++++++ install.conf.yaml | 1 + 4 files changed, 34 insertions(+) create mode 100644 configs/ssh/allowed_signers diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 980d51d..75499b2 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -1,10 +1,31 @@ [user] email = ewpratten@gmail.com name = Evan Pratten + # signingkey = + +# [core] +# editor = "vim" + +# [gpg] +# format = ssh + +[gpg "ssh"] + allowedSignersFile = ~/.ssh/allowed_signers + [filter "lfs"] clean = git-lfs clean -- %f smudge = git-lfs smudge -- %f process = git-lfs filter-process required = true + [url "ssh://git@github.com/"] insteadOf = https://github.com/ + +[credential "https://github.com"] + helper = + helper = !/usr/bin/gh auth git-credential + +[credential "https://gist.github.com"] + helper = + helper = !/usr/bin/gh auth git-credential + diff --git a/configs/ssh/allowed_signers b/configs/ssh/allowed_signers new file mode 100644 index 0000000..d0e1f83 --- /dev/null +++ b/configs/ssh/allowed_signers @@ -0,0 +1 @@ +evan@ewpratten.com sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAkdmKF1cYQTW7cfK7TYC5iVBsAg5g3SRJqlqo2NixHdAAAABHNzaDo= diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 15ce3ef..0990deb 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -20,6 +20,17 @@ fi export PATH="$HOME/bin:$PATH" export PATH="$HOME/.local/bin:$PATH" +# Configure a sane default editor +if type -p nvim > /dev/null; then + export EDITOR="nvim" +elif type -p vim > /dev/null; then + export EDITOR="vim" +elif type -p vi > /dev/null; then + export EDITOR="vi" +elif type -p nano > /dev/null; then + export EDITOR="nano" +fi + # SDKMAN! export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" diff --git a/install.conf.yaml b/install.conf.yaml index e98a2eb..ee74002 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -34,6 +34,7 @@ ~/.local/share/nautilus/scripts/Copy to web: path: configs/nautilus/scripts/Copy to web mode: 755 + ~/.ssh/allowed_signers: configs/ssh/allowed_signers - shell: - [git submodule update --init --recursive, Installing submodules] From 18df56ac4a5e3c7106859171029006c6e82bb1a9 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 14 Jun 2023 12:31:09 -0400 Subject: [PATCH 061/326] Set more sensible defaults & Added a macro --- configs/git/.gitconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 75499b2..ba226e0 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -9,6 +9,15 @@ # [gpg] # format = ssh +[init] + defaultBranch = master + +[advice] + detachedHead = true + +[alias] + authors = shortlog --summary --numbered --email + [gpg "ssh"] allowedSignersFile = ~/.ssh/allowed_signers From d160689f9944ec5797f1cc0cc61b3189ef2e8fd3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 17 Jun 2023 11:10:24 -0400 Subject: [PATCH 062/326] Configure cargo to use system git binary --- configs/cargo/config.toml | 2 ++ install.conf.yaml | 1 + 2 files changed, 3 insertions(+) create mode 100644 configs/cargo/config.toml diff --git a/configs/cargo/config.toml b/configs/cargo/config.toml new file mode 100644 index 0000000..656e08b --- /dev/null +++ b/configs/cargo/config.toml @@ -0,0 +1,2 @@ +[net] +git-fetch-with-cli = true \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index ee74002..1074965 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -35,6 +35,7 @@ path: configs/nautilus/scripts/Copy to web mode: 755 ~/.ssh/allowed_signers: configs/ssh/allowed_signers + ~/.cargo/config.toml: configs/cargo/config.toml - shell: - [git submodule update --init --recursive, Installing submodules] From a20bfd38f1eca4fe80f1ac75a4b8f4bae00c8d42 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 27 Jun 2023 21:48:13 -0400 Subject: [PATCH 063/326] Directly bundle vim plugins --- .gitmodules | 17 +++++++++++++++++ configs/nvim/pack/airblade/start/vim-gitgutter | 1 + configs/nvim/pack/ggandor/start/leap.nvim | 1 + configs/nvim/pack/jiangmiao/start/auto-pairs | 1 + configs/nvim/pack/tpope/start/commentary | 1 + configs/nvim/pack/tpope/start/repeat | 1 + 6 files changed, 22 insertions(+) create mode 160000 configs/nvim/pack/airblade/start/vim-gitgutter create mode 160000 configs/nvim/pack/ggandor/start/leap.nvim create mode 160000 configs/nvim/pack/jiangmiao/start/auto-pairs create mode 160000 configs/nvim/pack/tpope/start/commentary create mode 160000 configs/nvim/pack/tpope/start/repeat diff --git a/.gitmodules b/.gitmodules index 1af14d0..64ba8bc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,20 @@ path = dotbot url = https://github.com/anishathalye/dotbot ignore = dirty +[submodule "configs/nvim/pack/tpope/start/repeat"] + path = configs/nvim/pack/tpope/start/repeat + url = https://tpope.io/vim/repeat.git + ignore = dirty +[submodule "configs/nvim/pack/ggandor/start/leap.nvim"] + path = configs/nvim/pack/ggandor/start/leap.nvim + url = https://github.com/ggandor/leap.nvim + ignore = dirty +[submodule "configs/nvim/pack/tpope/start/commentary"] + path = configs/nvim/pack/tpope/start/commentary + url = https://tpope.io/vim/commentary.git +[submodule "configs/nvim/pack/jiangmiao/start/auto-pairs"] + path = configs/nvim/pack/jiangmiao/start/auto-pairs + url = https://github.com/jiangmiao/auto-pairs +[submodule "configs/nvim/pack/airblade/start/vim-gitgutter"] + path = configs/nvim/pack/airblade/start/vim-gitgutter + url = https://github.com/airblade/vim-gitgutter.git diff --git a/configs/nvim/pack/airblade/start/vim-gitgutter b/configs/nvim/pack/airblade/start/vim-gitgutter new file mode 160000 index 0000000..4a7ca06 --- /dev/null +++ b/configs/nvim/pack/airblade/start/vim-gitgutter @@ -0,0 +1 @@ +Subproject commit 4a7ca061af2b199a9b97041270611439e8fa2b02 diff --git a/configs/nvim/pack/ggandor/start/leap.nvim b/configs/nvim/pack/ggandor/start/leap.nvim new file mode 160000 index 0000000..dabcce4 --- /dev/null +++ b/configs/nvim/pack/ggandor/start/leap.nvim @@ -0,0 +1 @@ +Subproject commit dabcce410ea8655f3c0acaee8da8f366b4a629a8 diff --git a/configs/nvim/pack/jiangmiao/start/auto-pairs b/configs/nvim/pack/jiangmiao/start/auto-pairs new file mode 160000 index 0000000..39f06b8 --- /dev/null +++ b/configs/nvim/pack/jiangmiao/start/auto-pairs @@ -0,0 +1 @@ +Subproject commit 39f06b873a8449af8ff6a3eee716d3da14d63a76 diff --git a/configs/nvim/pack/tpope/start/commentary b/configs/nvim/pack/tpope/start/commentary new file mode 160000 index 0000000..e87cd90 --- /dev/null +++ b/configs/nvim/pack/tpope/start/commentary @@ -0,0 +1 @@ +Subproject commit e87cd90dc09c2a203e13af9704bd0ef79303d755 diff --git a/configs/nvim/pack/tpope/start/repeat b/configs/nvim/pack/tpope/start/repeat new file mode 160000 index 0000000..24afe92 --- /dev/null +++ b/configs/nvim/pack/tpope/start/repeat @@ -0,0 +1 @@ +Subproject commit 24afe922e6a05891756ecf331f39a1f6743d3d5a From 747bf3de2dca7ca3efe3f92765127679827455cc Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 27 Jun 2023 21:48:29 -0400 Subject: [PATCH 064/326] Re-configure for embedded vim plugins --- .gitmodules | 3 +++ configs/nvim/init.vim | 52 +++++++++++++------------------------------ 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/.gitmodules b/.gitmodules index 64ba8bc..9a866fe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,9 +13,12 @@ [submodule "configs/nvim/pack/tpope/start/commentary"] path = configs/nvim/pack/tpope/start/commentary url = https://tpope.io/vim/commentary.git + ignore = dirty [submodule "configs/nvim/pack/jiangmiao/start/auto-pairs"] path = configs/nvim/pack/jiangmiao/start/auto-pairs url = https://github.com/jiangmiao/auto-pairs + ignore = dirty [submodule "configs/nvim/pack/airblade/start/vim-gitgutter"] path = configs/nvim/pack/airblade/start/vim-gitgutter url = https://github.com/airblade/vim-gitgutter.git + ignore = dirty diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index d47bc7e..47954ae 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -21,7 +21,14 @@ vnoremap +inoremap +inoremap lcw +nnoremap cwl + +" VSCode-style comment toggling +nnoremap :Commentary +vnoremap :Commentary +inoremap :Commentary " Force VIM to use system clipboard set clipboard=unnamedplus @@ -30,44 +37,17 @@ set clipboard=unnamedplus set exrc set secure -" Autoload vim-plug -let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim' -if empty(glob(data_dir . '/autoload/plug.vim')) - silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' - autocmd VimEnter * PlugInstall --sync | source $MYVIMRC -endif - -" This is where the plugins be -call plug#begin() - -" Plug 'github/copilot.vim' -Plug 'tpope/vim-fugitive' -Plug 'tpope/vim-surround' -Plug 'jiangmiao/auto-pairs' -Plug 'airblade/vim-gitgutter' -Plug 'nathanaelkane/vim-indent-guides' - -" And this is where the plugins no longer be -call plug#end() - " Enable filetype plugins set nocompatible filetype plugin on syntax on -" Enable rainbow -let g:rainbow_active = 1 - -" Allow indent guides to show -let g:indent_guides_enable_on_vim_startup = 0 -let g:indent_guides_guide_size = 1 -let g:indent_guides_auto_colors = 0 -hi IndentGuidesOdd ctermbg=darkgrey -hi IndentGuidesEven ctermbg=lightgrey - -" Make the gitgutter look cleaner -let g:gitgutter_override_sign_column_highlight = 0 +" Disable the gitgutter background +let g:gitgutter_override_sign_column_highlight = 1 highlight clear SignColumn -highlight GitGutterAdd guifg=#009900 ctermfg=2 -highlight GitGutterChange guifg=#bbbb00 ctermfg=3 -highlight GitGutterDelete guifg=#ff2222 ctermfg=1 + +" Make gitgutter update on file save +autocmd BufWritePost * GitGutter + +" Enable Leap +lua require('leap').add_default_mappings() \ No newline at end of file From 06493b92c66a68df14ba077fd227eaa218bc9e96 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 27 Jun 2023 22:04:40 -0400 Subject: [PATCH 065/326] Switch prompt to 24H format --- configs/zsh/prompt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/zsh/prompt.sh b/configs/zsh/prompt.sh index 62b6cec..1ae5fbe 100644 --- a/configs/zsh/prompt.sh +++ b/configs/zsh/prompt.sh @@ -30,4 +30,4 @@ vcs_info_wrapper() { echo "%{$fg[grey]%}${vcs_info_msg_0_}%{$reset_color%}$del" fi } -export RPROMPT=$'%@ $(vcs_info_wrapper) %?' +export RPROMPT=$'%T $(vcs_info_wrapper)%?' From 8c82261cc1c15cebb18eb9f2c729e5e9cb127fd0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 27 Jun 2023 22:51:12 -0400 Subject: [PATCH 066/326] Improve command history --- configs/zsh/autocomplete.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/configs/zsh/autocomplete.sh b/configs/zsh/autocomplete.sh index 868cd3b..62760a0 100644 --- a/configs/zsh/autocomplete.sh +++ b/configs/zsh/autocomplete.sh @@ -1,3 +1,5 @@ +# Make all shells append to history file instantly +setopt INC_APPEND_HISTORY # Handles case-insensitive completion autoload -Uz compinit && compinit @@ -5,8 +7,15 @@ zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' # Configure command history HISTFILE=~/.histfile -HISTSIZE=1000 -SAVEHIST=1000 +HISTSIZE=100000 +SAVEHIST=100000 + +# Ignore duplicates in history search, and dont't write them either +setopt HIST_FIND_NO_DUPS +setopt HIST_IGNORE_ALL_DUPS + +# Ignore commands starting with a space +setopt HIST_IGNORE_SPACE # Allow up arrow to be used to go back in history based on current line contents autoload -U up-line-or-beginning-search @@ -14,4 +23,4 @@ autoload -U down-line-or-beginning-search zle -N up-line-or-beginning-search zle -N down-line-or-beginning-search bindkey "^[[A" up-line-or-beginning-search # Up -bindkey "^[[B" down-line-or-beginning-search # Down \ No newline at end of file +bindkey "^[[B" down-line-or-beginning-search # Down From 8cb0b4c450516c83ef2357258f68f4d065b60751 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 30 Jun 2023 11:23:24 -0400 Subject: [PATCH 067/326] Configured spellchecking and some macros --- configs/nvim/init.vim | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 47954ae..56a0ac6 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -5,6 +5,17 @@ syntax on " Enable mouse usage set mouse=a +" Configure the right-click menu +aunmenu PopUp +vnoremenu PopUp.Cut "+x +vnoremenu PopUp.Copy "+y +anoremenu PopUp.Paste "+gP +vnoremenu PopUp.Paste "+P +vnoremenu PopUp.Delete "_x +nnoremenu PopUp.Select\ All> ggVG +vnoremenu PopUp.Select\ All> gg0oG$ +inoremenu PopUp.Select\ All VG + " Tab size set tabstop=4 set shiftwidth=4 @@ -42,6 +53,20 @@ set nocompatible filetype plugin on syntax on +" Hide the intro message +set shortmess+=I + +" Force help documents into new tabs +cnoreabbrev help getcmdtype() == ":" && getcmdline() == 'help' ? 'tab help' : 'help' +cnoreabbrev h getcmdtype() == ":" && getcmdline() == 'h' ? 'tab help' : 'h' + +" Enable spell checking +set spell +set spelllang=en_ca,en_us +set spelloptions=camel +hi clear SpellCap +hi clear SpellRare + " Disable the gitgutter background let g:gitgutter_override_sign_column_highlight = 1 highlight clear SignColumn @@ -50,4 +75,4 @@ highlight clear SignColumn autocmd BufWritePost * GitGutter " Enable Leap -lua require('leap').add_default_mappings() \ No newline at end of file +lua require('leap').add_default_mappings() From f5ceae7abd0420a3199240f051a139abd1d9fbdc Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 1 Jul 2023 14:09:24 -0400 Subject: [PATCH 068/326] Fixing minor bugs with git and nvim --- configs/git/.gitconfig | 3 ++- configs/nvim/.gitignore | 2 ++ install.conf.yaml | 27 +++++++++++++++++++++------ 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 configs/nvim/.gitignore diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index ba226e0..720a7df 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -28,7 +28,8 @@ required = true [url "ssh://git@github.com/"] - insteadOf = https://github.com/ + #insteadOf = https://github.com/ + pushInsteadOf = https://github.com/ [credential "https://github.com"] helper = diff --git a/configs/nvim/.gitignore b/configs/nvim/.gitignore new file mode 100644 index 0000000..aff9f31 --- /dev/null +++ b/configs/nvim/.gitignore @@ -0,0 +1,2 @@ +/spell + diff --git a/install.conf.yaml b/install.conf.yaml index 1074965..9b1e571 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -5,23 +5,34 @@ - clean: ['~'] - create: + # Common organizational dirs - ~/Downloads - ~/bin - ~/projects - ~/src - ~/www - ~/pkg + # Config dirs + - ~/.config/nvim + # Program plugins - ~/.local/share/nautilus/scripts/ - + - link: + # Git ~/.gitconfig: configs/git/.gitconfig + ~/.ssh/allowed_signers: configs/ssh/allowed_signers + + # Shell ~/.zshrc: path: configs/zsh/.zshrc force: true - ~/.config/tabset: configs/tabset - ~/.config/rofi: configs/rofi - # ~/.local/share/remmina: configs/remmina/hosts - ~/.config/nvim: configs/nvim + + # Vim + ~/.config/nvim/init.vim: configs/nvim/init.vim + ~/.config/nvim/pack: configs/nvim/pack + # ~/.config/nvim/spell: configs/nvim/en.utf-8.add + + # Scripts ~/bin/catto: path: configs/scripts/catto mode: 755 @@ -34,7 +45,11 @@ ~/.local/share/nautilus/scripts/Copy to web: path: configs/nautilus/scripts/Copy to web mode: 755 - ~/.ssh/allowed_signers: configs/ssh/allowed_signers + + # Others + ~/.config/tabset: configs/tabset + ~/.config/rofi: configs/rofi + # ~/.local/share/remmina: configs/remmina/hosts ~/.cargo/config.toml: configs/cargo/config.toml - shell: From f0bb77323ae391838c76df5e9363d7b5d096bc40 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 1 Jul 2023 14:19:21 -0400 Subject: [PATCH 069/326] Auto-gen cargo config dir on systems without rust for compatibility --- install.conf.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/install.conf.yaml b/install.conf.yaml index 9b1e571..00fd00b 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -14,6 +14,7 @@ - ~/pkg # Config dirs - ~/.config/nvim + - ~/.config/cargo # Program plugins - ~/.local/share/nautilus/scripts/ From cfdae3d8fdd826588bdf2bfde6fab810f60fb662 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 1 Jul 2023 14:21:36 -0400 Subject: [PATCH 070/326] Auto-set git pull mode --- configs/git/.gitconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 720a7df..78e0a85 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -12,6 +12,9 @@ [init] defaultBranch = master +[pull] + rebase = false + [advice] detachedHead = true From 676de7192331a8e458e510400e2511b2b6c39b1c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 1 Jul 2023 14:22:30 -0400 Subject: [PATCH 071/326] Correct cargo config dir --- install.conf.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.conf.yaml b/install.conf.yaml index 00fd00b..e75163e 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -14,7 +14,7 @@ - ~/pkg # Config dirs - ~/.config/nvim - - ~/.config/cargo + - ~/.cargo # Program plugins - ~/.local/share/nautilus/scripts/ From fcee01b0b59c7cf8612c67e8e8b8270eb2716521 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 2 Jul 2023 23:14:59 -0400 Subject: [PATCH 072/326] Configure termux --- configs/nvim/init.vim | 36 +++++++++++++++++++------------- configs/termux/termux.properties | 7 +++++++ install.conf.yaml | 3 +++ 3 files changed, 31 insertions(+), 15 deletions(-) create mode 100644 configs/termux/termux.properties diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 56a0ac6..1a2d0b3 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -6,15 +6,17 @@ syntax on set mouse=a " Configure the right-click menu -aunmenu PopUp -vnoremenu PopUp.Cut "+x -vnoremenu PopUp.Copy "+y -anoremenu PopUp.Paste "+gP -vnoremenu PopUp.Paste "+P -vnoremenu PopUp.Delete "_x -nnoremenu PopUp.Select\ All> ggVG -vnoremenu PopUp.Select\ All> gg0oG$ -inoremenu PopUp.Select\ All VG +if !exists('g:vscode') + aunmenu PopUp + vnoremenu PopUp.Cut "+x + vnoremenu PopUp.Copy "+y + anoremenu PopUp.Paste "+gP + vnoremenu PopUp.Paste "+P + vnoremenu PopUp.Delete "_x + nnoremenu PopUp.Select\ All> ggVG + vnoremenu PopUp.Select\ All> gg0oG$ + inoremenu PopUp.Select\ All VG +endif " Tab size set tabstop=4 @@ -61,18 +63,22 @@ cnoreabbrev help getcmdtype() == ":" && getcmdline() == 'help' ? 'tab hel cnoreabbrev h getcmdtype() == ":" && getcmdline() == 'h' ? 'tab help' : 'h' " Enable spell checking -set spell -set spelllang=en_ca,en_us -set spelloptions=camel -hi clear SpellCap -hi clear SpellRare +if !exists('g:vscode') + set spell + set spelllang=en_ca,en_us + set spelloptions=camel + hi clear SpellCap + hi clear SpellRare +endif " Disable the gitgutter background let g:gitgutter_override_sign_column_highlight = 1 highlight clear SignColumn " Make gitgutter update on file save -autocmd BufWritePost * GitGutter +if !exists('g:vscode') + autocmd BufWritePost * GitGutter +endif " Enable Leap lua require('leap').add_default_mappings() diff --git a/configs/termux/termux.properties b/configs/termux/termux.properties new file mode 100644 index 0000000..9f8a262 --- /dev/null +++ b/configs/termux/termux.properties @@ -0,0 +1,7 @@ +# Terminal behaviour +bell-character=vibrate + +# Keyboard +extra-keys-style = default +extra-keys = [['ESC', 'TAB', 'CTRL', 'ALT', 'LEFT', 'DOWN', 'UP', 'RIGHT']] + diff --git a/install.conf.yaml b/install.conf.yaml index e75163e..cd90227 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -14,6 +14,7 @@ - ~/pkg # Config dirs - ~/.config/nvim + - ~/.config/termux - ~/.cargo # Program plugins - ~/.local/share/nautilus/scripts/ @@ -52,6 +53,7 @@ ~/.config/rofi: configs/rofi # ~/.local/share/remmina: configs/remmina/hosts ~/.cargo/config.toml: configs/cargo/config.toml + ~/.config/termux/termux.properties: configs/termux/termux.properties - shell: - [git submodule update --init --recursive, Installing submodules] @@ -60,3 +62,4 @@ - [chmod +x configs/scripts/aspath, Making aspath executable] - [chmod +x configs/scripts/fetch-steamdeck-screenshots, Making fetch-steamdeck-screenshots executable] - [sh ./helpers/configure-gnome.sh, Configuring GNOME] + - [termux-reload-settings || true, Trying to reload Termux] From a8ea9c87d35b2ee571ed2fd0bd552a22ecb072ec Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 2 Jul 2023 23:24:12 -0400 Subject: [PATCH 073/326] Collapse hostname on Termux --- configs/zsh/prompt.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configs/zsh/prompt.sh b/configs/zsh/prompt.sh index 1ae5fbe..915c345 100644 --- a/configs/zsh/prompt.sh +++ b/configs/zsh/prompt.sh @@ -12,7 +12,16 @@ else HOST_COLOR="green" fi -export PROMPT="%{$fg[$HOST_COLOR]%}%n@%M %{$fg[cyan]%}%~ $ %{$reset_color%}" +# Clear the prompt +export PROMPT="" + +# If we are *NOT* in Termux, show the host and username +if ! command -v termux-setup-storage; then + export PROMPT="%{$fg[$HOST_COLOR]%}%n@%M " +fi + +# Add the common prompt parts +export PROMPT="${PROMPT}%{$fg[cyan]%}%~ $ %{$reset_color%}" setopt prompt_subst autoload -Uz vcs_info zstyle ':vcs_info:*' actionformats \ From 029db6e06259d73612591370a44f27c3d9fbac8b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 3 Jul 2023 15:17:28 -0400 Subject: [PATCH 074/326] Added a "Write and Mkdir" command --- configs/nvim/init.vim | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 1a2d0b3..fe2a4a1 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -82,3 +82,11 @@ endif " Enable Leap lua require('leap').add_default_mappings() + +" Custom functions +function! MkdirAndWrite() + let dir = expand('%:p:h') + exec '!mkdir -p ' . dir + exec 'w' +endfunction +command Wmk call MkdirAndWrite() From 3132af01d3e490a469af1db046317af8ec3e321f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 6 Jul 2023 14:24:09 -0400 Subject: [PATCH 075/326] Add a color code for docker containers --- configs/zsh/prompt.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/zsh/prompt.sh b/configs/zsh/prompt.sh index 915c345..dd2308c 100644 --- a/configs/zsh/prompt.sh +++ b/configs/zsh/prompt.sh @@ -8,6 +8,8 @@ NEWLINE=$'\n' # Use colors to signal local vs remote connections if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then HOST_COLOR="yellow" +elif [ "$EWCONFIG_IN_DOCKER" = "1" ]; then + HOST_COLOR="blue" else HOST_COLOR="green" fi From 5b6f653e040046dd3bb13e2d8e66562925cf950f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 10:46:17 -0400 Subject: [PATCH 076/326] Improved handling of SSH auth --- configs/ssh/config | 42 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index 72c8db8..9ce9a7c 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -1,3 +1,10 @@ +# Global Rules +Host * + IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 + IdentityFile %d/.ssh/id_ed25519 + IdentityFile %d/.ssh/id_rsa + VisualHostKey yes + # Github SSH adapter for restricted networks Host github.com HostName ssh.github.com @@ -19,11 +26,6 @@ Host ewpratten-steamdeck User deck ForwardX11 yes -Host mc.homieho.me - User root - PreferredAuthentications password - PubkeyAuthentication no - Host 10.80.0.218 User root PreferredAuthentications password @@ -31,25 +33,6 @@ Host 10.80.0.218 PubkeyAcceptedKeyTypes +ssh-rsa HostKeyAlgorithms=+ssh-rsa -# IndustrialBrothers domain -Host ib-* - Hostname %h.industrialbrothers.com - IdentityFile ~/.ssh/industrialbrothers_id_ed25519 - RequestTTY force - User epratten - -Host *.industrialbrothers.com - IdentityFile ~/.ssh/industrialbrothers_id_ed25519 - User epratten - -Host ib-8700k-125 - RemoteCommand powershell "& 'C:\Program Files\Git\bin\sh.exe' --login" -Host ib-8700k-139 - RemoteCommand powershell "& 'C:\Program Files\Git\bin\sh.exe' --login" - -Host ib-rfcpu-002-lnx - User evan - # Default hostnames I may encounter in the wild Host openrepeater.local HostName openrepeater.local @@ -72,17 +55,12 @@ Host 10.50.24.2 StrictHostKeyChecking no User admin -# Sheridan -Host atlas +# Sheridan College +Host *.sheridanc.on.ca User prattene RequestTTY yes - # RemoteCommand ~/.local/bin/zsh --login - -Host sheridan-cpanel - User prattene - HostName cpanel.prattene.dev.fast.sheridanc.on.ca PubkeyAcceptedKeyTypes +ssh-rsa - HostKeyAlgorithms=+ssh-rsa + HostKeyAlgorithms +ssh-rsa # NLNOG Host *.ring.nlnog.net From 21adb00f7fed8d7769657ffec7e5596cafeca2f3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:15:24 -0400 Subject: [PATCH 077/326] Add support for manpages in neovim --- configs/nvim/init.vim | 3 +++ configs/zsh/.zshrc | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index fe2a4a1..2215d24 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -69,6 +69,9 @@ if !exists('g:vscode') set spelloptions=camel hi clear SpellCap hi clear SpellRare + + " Disable spellcheck for manpages + autocmd FileType man setlocal nospell endif " Disable the gitgutter background diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 0990deb..60015ff 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -31,6 +31,12 @@ elif type -p nano > /dev/null; then export EDITOR="nano" fi +# If we have neovim, use it as the manpage viewer +if type -p nvim > /dev/null; then + export MANPAGER="nvim +Man!" + export MANWIDTH=80 +fi + # SDKMAN! export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" From 95792dbd3c2ae3fb526d4a9c31aee884b889f12c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:16:50 -0400 Subject: [PATCH 078/326] change title text --- README.md | 17 +---------------- configs/pkcs11/modules/opensc.module | 12 ++++++++++++ 2 files changed, 13 insertions(+), 16 deletions(-) create mode 100644 configs/pkcs11/modules/opensc.module diff --git a/README.md b/README.md index 262f06b..e3addf0 100644 --- a/README.md +++ b/README.md @@ -1,16 +1 @@ -# ewconfig: My dotfiles - -## Neovim - -```sh -sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \ - https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim' -``` - -And in `nvim`, run - -```text -:PlugInstall -:Copilot setup -``` - +# **ew**pratten's **config** files diff --git a/configs/pkcs11/modules/opensc.module b/configs/pkcs11/modules/opensc.module new file mode 100644 index 0000000..9cb6765 --- /dev/null +++ b/configs/pkcs11/modules/opensc.module @@ -0,0 +1,12 @@ +# This file describes how to load the opensc module +# See: https://p11-glue.github.io/p11-glue/p11-kit/manual/pkcs11-conf.html +# or man pkcs11.conf + +# This is a relative path, which means it will be loaded from +# the p11-kit default path which is usually $(libdir)/pkcs11. +# Doing it this way allows for packagers to package opensc for +# 32-bit and 64-bit and make them parallel installable +module: opensc-pkcs11.so + +# Disables annoying password popup when a Yubikey is left plugged in to a system +disable-in: firefox vivaldi-bin thunderbird From 29852c160a7fb2ed806c098ca96f37f9c25085ae Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:17:37 -0400 Subject: [PATCH 079/326] apparently github cant render that --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e3addf0..7ef2fdb 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# **ew**pratten's **config** files +# *ew*pratten's *config* files From eb26b11da2fd3a9f35a19571578a92416ba6f353 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:19:35 -0400 Subject: [PATCH 080/326] Add a little more info --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 7ef2fdb..5068b45 100644 --- a/README.md +++ b/README.md @@ -1 +1,14 @@ # *ew*pratten's *config* files + +```sh +mkdir -p ~/.config && cd ~/.config +git clone https://github.com/ewpratten/ewconfig +cd ewconfig +./install +``` + +## Dependencies + +- Git +- ZSH (optional, recommended) +- Neovim (optional, recommended) From c1c8b94410c0c1bf36b2fa2fd72fa8be8155f491 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:20:23 -0400 Subject: [PATCH 081/326] Test disabling hostkey vis for git --- configs/ssh/config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/ssh/config b/configs/ssh/config index 9ce9a7c..4981b48 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -9,10 +9,12 @@ Host * Host github.com HostName ssh.github.com Port 443 + VisualHostKey no Host gist.github.com HostName ssh.github.com Port 443 + VisualHostKey no # Home network Host unifi From 0c9d40655139271d3fc5fd3ba8488d35837376c8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:20:38 -0400 Subject: [PATCH 082/326] test --- configs/ssh/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/ssh/config b/configs/ssh/config index 4981b48..522b8b0 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -4,7 +4,7 @@ Host * IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_rsa VisualHostKey yes - + # Github SSH adapter for restricted networks Host github.com HostName ssh.github.com From f4448935b3c6717e5d26ff86e7bfdaefea784308 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:22:08 -0400 Subject: [PATCH 083/326] . --- configs/ssh/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/ssh/config b/configs/ssh/config index 522b8b0..4981b48 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -4,7 +4,7 @@ Host * IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_rsa VisualHostKey yes - + # Github SSH adapter for restricted networks Host github.com HostName ssh.github.com From 169585af5cf645a460de536bf57d5a3e0e304423 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:38:20 -0400 Subject: [PATCH 084/326] Use spaces for indentation --- configs/ssh/config | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index 4981b48..0a70c94 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -7,12 +7,12 @@ Host * # Github SSH adapter for restricted networks Host github.com - HostName ssh.github.com - Port 443 + HostName ssh.github.com + Port 443 VisualHostKey no Host gist.github.com - HostName ssh.github.com + HostName ssh.github.com Port 443 VisualHostKey no @@ -37,12 +37,12 @@ Host 10.80.0.218 # Default hostnames I may encounter in the wild Host openrepeater.local - HostName openrepeater.local - User root - StrictHostKeyChecking no + HostName openrepeater.local + User root + StrictHostKeyChecking no Host raspberrypi.local - StrictHostKeyChecking no + StrictHostKeyChecking no User pi Host 192.168.8.1 @@ -54,8 +54,8 @@ Host 192.168.8.1 # Raider Robotics Host 10.50.24.2 - StrictHostKeyChecking no - User admin + StrictHostKeyChecking no + User admin # Sheridan College Host *.sheridanc.on.ca From 2ce28511be4cdb0dc8b6f1927f160acfad8bd11f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 11:43:04 -0400 Subject: [PATCH 085/326] Better negation rule --- configs/ssh/config | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index 0a70c94..c7fe42a 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -3,18 +3,17 @@ Host * IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_rsa +Host * !*.github.com !github.com VisualHostKey yes # Github SSH adapter for restricted networks Host github.com HostName ssh.github.com Port 443 - VisualHostKey no Host gist.github.com HostName ssh.github.com Port 443 - VisualHostKey no # Home network Host unifi From 55ac191f082c4d50dc561640bc0826b38fc98dcf Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 25 Jul 2023 13:08:01 -0400 Subject: [PATCH 086/326] Improve key handling for SDF.org --- configs/ssh/config | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index c7fe42a..00d93bd 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -7,11 +7,7 @@ Host * !*.github.com !github.com VisualHostKey yes # Github SSH adapter for restricted networks -Host github.com - HostName ssh.github.com - Port 443 - -Host gist.github.com +Host github.com gist.github.com HostName ssh.github.com Port 443 @@ -67,18 +63,10 @@ Host *.sheridanc.on.ca Host *.ring.nlnog.net User ewpratten IdentitiesOnly yes - #IdentityFile ~/.ssh/id_ed25519_sk_rk.pub # SDF.org -Host *.sdf.org +Host sdf.org *.sdf.org user ewpratten - PreferredAuthentications password - PubkeyAuthentication no - -Host sdf.org - user ewpratten - PreferredAuthentications password - PubkeyAuthentication no # Personal Infra Host oci-arm From 4cf7f6f8bbea66788cda86637aacd2fa7057e498 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 26 Jul 2023 23:54:02 -0400 Subject: [PATCH 087/326] Add macros for signing things with SSH keys --- configs/ssh/allowed_signers | 3 +++ configs/zsh/macros.sh | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/configs/ssh/allowed_signers b/configs/ssh/allowed_signers index d0e1f83..0f1c41e 100644 --- a/configs/ssh/allowed_signers +++ b/configs/ssh/allowed_signers @@ -1 +1,4 @@ +evan@ewpratten.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMbNW3x0Cx04MybxQo5FptZhdjiFJjKITtq67KqrDXAN+jepJwdIG6TUJzuJddztuYIsvPAoQPpiQVSPyC8y51Y= evan@ewpratten.com sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAkdmKF1cYQTW7cfK7TYC5iVBsAg5g3SRJqlqo2NixHdAAAABHNzaDo= +evan@ewpratten.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBaSKoWYuR43fxRPy31P/X/2Ri2hYUZTjKiLBRDoa1F +evan@ewpratten.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGEqeWe+pVp3rTsmHr9v5Qcb+niHXihJxwVKcc7p6EXz diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 76d2c84..06080a7 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -95,3 +95,25 @@ genpass() { fi } + +# Sign a file with an SSH key +ssh-sign(){ + if [ $# != 2 ]; then + echo "Usage: ssh-sign " + else + if [ -f $2 ]; then + cat $2 | ssh-keygen -Y sign -f $1 -n file - + else + >&2 echo "File not found: $2" + fi + fi +} + +# Verify a file, using the ~/.ssh/allowed_signers file +ssh-verify(){ + if [ $# != 3 ]; then + echo "Usage: ssh-verify " + else + ssh-keygen -Y verify -f ~/.ssh/allowed_signers -n file -I $1 -s $2 < $3 + fi +} From bf1c784f854acf1924e7ceca38059dcfca2720f7 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 00:00:27 -0400 Subject: [PATCH 088/326] Disable gnome keyring on laptop --- configs/zsh/.zshrc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 60015ff..9f97e3c 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -37,6 +37,11 @@ if type -p nvim > /dev/null; then export MANWIDTH=80 fi +# Replace gnome-keyring with default ssh agent if possible +if type -p gnome-keyring-daemon > /dev/null; then + killall gnome-keyring-daemon 2> /dev/null && eval `ssh-agent` +fi + # SDKMAN! export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" From bbbb5bbff9802490bf616c45b9769f53f3d5e4a4 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 00:05:23 -0400 Subject: [PATCH 089/326] Enable gpg ssh sign --- configs/git/.gitconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 78e0a85..2549915 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -6,8 +6,8 @@ # [core] # editor = "vim" -# [gpg] -# format = ssh +[gpg] + format = ssh [init] defaultBranch = master @@ -22,7 +22,8 @@ authors = shortlog --summary --numbered --email [gpg "ssh"] - allowedSignersFile = ~/.ssh/allowed_signers + allowedSignersFile = ~/.ssh/allowed_signers + defaultKeyCommand = ssh-add -L [filter "lfs"] clean = git-lfs clean -- %f From b553ec2daaca8004c9bf3d4af462772589e177ac Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 11:06:27 -0400 Subject: [PATCH 090/326] Testing commit signing --- .vscode/settings.json | 10 ++++++++++ configs/git/.gitconfig | 5 +---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..58d16ed --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "files.associations": { + "*.json.liquid": "json", + "*.yaml.liquid": "yaml", + "*.md.liquid": "markdown", + "*.js.liquid": "liquid-javascript", + "*.css.liquid": "liquid-css", + "*.scss.liquid": "liquid-scss", + } +} \ No newline at end of file diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 2549915..7d9a6b1 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -1,10 +1,7 @@ [user] email = ewpratten@gmail.com name = Evan Pratten - # signingkey = - -# [core] -# editor = "vim" + signingkey = ~/.ssh/id_ed25519_sk_rk_yk20572395 [gpg] format = ssh From 59865a8091161a7290ced878a6afbdaedc173fff Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 11:27:23 -0400 Subject: [PATCH 091/326] Only use new agent on laptop --- configs/zsh/.zshrc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 9f97e3c..d558443 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -38,8 +38,10 @@ if type -p nvim > /dev/null; then fi # Replace gnome-keyring with default ssh agent if possible -if type -p gnome-keyring-daemon > /dev/null; then - killall gnome-keyring-daemon 2> /dev/null && eval `ssh-agent` +if HOSTNAME="ewpratten-laptop"; then + if type -p gnome-keyring-daemon > /dev/null; then + killall gnome-keyring-daemon 2> /dev/null && eval `ssh-agent` + fi fi # SDKMAN! From 09e8c5c4cec8dcf2205a533b78b62b5db0d6d341 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 11:29:50 -0400 Subject: [PATCH 092/326] fix syntax --- configs/zsh/.zshrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index d558443..76704df 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -38,7 +38,7 @@ if type -p nvim > /dev/null; then fi # Replace gnome-keyring with default ssh agent if possible -if HOSTNAME="ewpratten-laptop"; then +if [[ "$HOSTNAME" == "ewpratten-laptop" ]]; then if type -p gnome-keyring-daemon > /dev/null; then killall gnome-keyring-daemon 2> /dev/null && eval `ssh-agent` fi From d5da28d40fde1fcd0def1ee5575d6affc4c97bfe Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 11:44:04 -0400 Subject: [PATCH 093/326] Only enable SSH signing on supported hosts --- configs/git/.gitconfig | 10 +++------- configs/git/features/enable-signing.gitconfig | 6 ++++++ helpers/git-config-features.sh | 7 +++++++ install.conf.yaml | 1 + 4 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 configs/git/features/enable-signing.gitconfig create mode 100644 helpers/git-config-features.sh diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 7d9a6b1..700f478 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -1,11 +1,11 @@ +[include] + path = ~/.config/git/features/enable-signing.gitconfig + [user] email = ewpratten@gmail.com name = Evan Pratten signingkey = ~/.ssh/id_ed25519_sk_rk_yk20572395 -[gpg] - format = ssh - [init] defaultBranch = master @@ -18,10 +18,6 @@ [alias] authors = shortlog --summary --numbered --email -[gpg "ssh"] - allowedSignersFile = ~/.ssh/allowed_signers - defaultKeyCommand = ssh-add -L - [filter "lfs"] clean = git-lfs clean -- %f smudge = git-lfs smudge -- %f diff --git a/configs/git/features/enable-signing.gitconfig b/configs/git/features/enable-signing.gitconfig new file mode 100644 index 0000000..f392a2a --- /dev/null +++ b/configs/git/features/enable-signing.gitconfig @@ -0,0 +1,6 @@ +[gpg] + format = ssh + +[gpg "ssh"] + allowedSignersFile = ~/.ssh/allowed_signers + defaultKeyCommand = ssh-add -L \ No newline at end of file diff --git a/helpers/git-config-features.sh b/helpers/git-config-features.sh new file mode 100644 index 0000000..5736766 --- /dev/null +++ b/helpers/git-config-features.sh @@ -0,0 +1,7 @@ +#! /bin/bash +set -e + +if [[ "$HOSTNAME" == "fedora" ]] || [[ "$HOSTNAME" == "ewpratten-laptop" ]]; then + mkdir -p $HOME/.config/git/features + ln -sf $EWCONFIG_ROOT/configs/git/features/enable-signing.gitconfig $HOME/.config/git/features/enable-signing.gitconfig +fi \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index cd90227..17c0203 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -63,3 +63,4 @@ - [chmod +x configs/scripts/fetch-steamdeck-screenshots, Making fetch-steamdeck-screenshots executable] - [sh ./helpers/configure-gnome.sh, Configuring GNOME] - [termux-reload-settings || true, Trying to reload Termux] + - [bash ./helpers/git-config-features.sh, Setting up optional git-config features] From f4d3135307f48e94533b2d49a0078a4dd0fbe0c0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 11:52:09 -0400 Subject: [PATCH 094/326] Indicate root --- configs/zsh/prompt.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/configs/zsh/prompt.sh b/configs/zsh/prompt.sh index dd2308c..d107017 100644 --- a/configs/zsh/prompt.sh +++ b/configs/zsh/prompt.sh @@ -4,9 +4,13 @@ autoload -U colors && colors NEWLINE=$'\n' +USER_ICON="$" -# Use colors to signal local vs remote connections -if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then +# Use colors to signal the current connection / user privs +if [[ $(id -u) = 0 ]]; then + HOST_COLOR="red" + USER_ICON="#" +elif [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then HOST_COLOR="yellow" elif [ "$EWCONFIG_IN_DOCKER" = "1" ]; then HOST_COLOR="blue" @@ -23,7 +27,7 @@ if ! command -v termux-setup-storage; then fi # Add the common prompt parts -export PROMPT="${PROMPT}%{$fg[cyan]%}%~ $ %{$reset_color%}" +export PROMPT="${PROMPT}%{$fg[cyan]%}%~ ${USER_ICON} %{$reset_color%}" setopt prompt_subst autoload -Uz vcs_info zstyle ':vcs_info:*' actionformats \ From 15a65f4fdbdb62cdbff8aa29aaa61b89c15a6c71 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 11:53:22 -0400 Subject: [PATCH 095/326] Force green for header --- configs/zsh/info.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/zsh/info.sh b/configs/zsh/info.sh index 2a9c182..e4dcff5 100644 --- a/configs/zsh/info.sh +++ b/configs/zsh/info.sh @@ -1,5 +1,5 @@ -echo "$fg[$HOST_COLOR]Platform:$reset_color $(uname -o) $(uname -r)" -echo "$fg[$HOST_COLOR]Uptime:$reset_color $(uptime -p)" +echo "$fg[green]Platform:$reset_color $(uname -o) $(uname -r)" +echo "$fg[green]Uptime:$reset_color $(uptime -p)" # Determine if $EWCONFIG_ROOT contains uncommitted changes if [ -d $EWCONFIG_ROOT/.git ]; then From 613d811975a5b6b8f69b56fe2e9c3659209f8f2f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 12:00:48 -0400 Subject: [PATCH 096/326] Add macros for handling wg links --- configs/zsh/macros.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 06080a7..4bc77e9 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -117,3 +117,21 @@ ssh-verify(){ ssh-keygen -Y verify -f ~/.ssh/allowed_signers -n file -I $1 -s $2 < $3 fi } + +# Fully restart a wireguard link +wg-restart() { + if [ $# != 1 ]; then + echo "Usage: wg-restart " + else + wg-quick down $1 && wg-quick up $1 + fi +} + +# Reload a wireguard link without stopping it +wg-reload() { + if [ $# != 1 ]; then + echo "Usage: wg-reload " + else + wg syncconf $1 <(wg-quick strip $1) + fi +} \ No newline at end of file From 3eb899d37ad8459238b72069338d2740f78a01de Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 27 Jul 2023 12:43:25 -0400 Subject: [PATCH 097/326] Enable rust autocomplete --- configs/zsh/autocomplete.sh | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/configs/zsh/autocomplete.sh b/configs/zsh/autocomplete.sh index 62760a0..dbcb70d 100644 --- a/configs/zsh/autocomplete.sh +++ b/configs/zsh/autocomplete.sh @@ -1,8 +1,25 @@ +# Allow programs to write their own autocomplete functions to ~/.zfunc +mkdir -p ~/.zfunc +fpath+=~/.zfunc + # Make all shells append to history file instantly setopt INC_APPEND_HISTORY -# Handles case-insensitive completion +# If we have rustup, it can be used to generate completeions for itself and cargo +if type -p rustup >/dev/null; then + # Only generate if the files don't already exist + if [[ ! -f ~/.zfunc/_rustup ]]; then + rustup completions zsh > ~/.zfunc/_rustup + fi + if [[ ! -f ~/.zfunc/_cargo ]]; then + rustup completions zsh cargo > ~/.zfunc/_cargo + fi +fi + +# Enable auto-complete autoload -Uz compinit && compinit + +# Handles case-insensitive completion zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' # Configure command history From 562aea2600bdc0dbb53d158ca068bb2c57af9662 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 29 Jul 2023 12:57:48 -0400 Subject: [PATCH 098/326] fixing some startup issues --- configs/autostart/gnome-keyring-ssh.desktop | 157 ++++++++++++++++++++ configs/user-tmpfiles.d/discord-rpc.conf | 1 + configs/zsh/.zshrc | 7 - install.conf.yaml | 2 + 4 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 configs/autostart/gnome-keyring-ssh.desktop create mode 100644 configs/user-tmpfiles.d/discord-rpc.conf diff --git a/configs/autostart/gnome-keyring-ssh.desktop b/configs/autostart/gnome-keyring-ssh.desktop new file mode 100644 index 0000000..a46a76a --- /dev/null +++ b/configs/autostart/gnome-keyring-ssh.desktop @@ -0,0 +1,157 @@ +[Desktop Entry] +Hidden=true +Type=Application +Name[af]=SSH-sleutelagent +Name[ar]=عميل مفاتيح SSH +Name[as]=SSH কি সহায়ক +Name[ast]=Axente de claves SSH +Name[be]=SSH-агент ключоў +Name[bg]=Агентът на SSH за ключове +Name[bn]=SSH কী এজেন্ট +Name[bn_IN]=SSH কি এজেন্ট +Name[bs]=Agent za SSH ključeve +Name[ca]=Agent de claus SSH +Name[ca@valencia]=Agent de claus SSH +Name[cs]=Agent klíčů SSH +Name[da]=SSH-nøgleagent +Name[de]=SSH-Schlüsselagent +Name[el]=Πράκτορας κλειδιού SSH +Name[en_GB]=SSH Key Agent +Name[eo]=SSH-ŝlosila agento +Name[es]=Agente de claves SSH +Name[et]=SSH-võtmete agent +Name[eu]=SSH gako-agentea +Name[fa]=عامل کلید SSH +Name[fi]=SSH-avainten agentti +Name[fr]=Agent de clés SSH +Name[fur]=Agjent clâfs SSH +Name[gd]=Àidseant iuchair SSH +Name[gl]=Axente de chave SSH +Name[gu]=SSH કી ઍજન્ટ +Name[he]=סוכן מפתחות SSH +Name[hi]=AFS कुँजी प्रतिनिधि +Name[hr]=Agent SSH ključa +Name[hu]=SSH-kulcs ügynök +Name[id]=Agen Kunci SSH +Name[it]=Agente chiavi SSH +Name[ja]=SSH 鍵エージェント +Name[kk]=SSH кілттер агенті +Name[km]=ភ្នាក់ងារ​សោ SSH +Name[kn]=SSH ಕೀಲಿ ಮಧ್ಯವರ್ತಿ +Name[ko]=SSH 키 에이전트 +Name[lt]=SSH raktų tarnyba +Name[lv]=SSH atslēgu aģents +Name[mjw]=SSH Key Agent +Name[mk]=Агент за SSH клучеви +Name[ml]=എസ്എസ്എച് കീ ഏജന്റ് +Name[mr]=SSH कि एजंट +Name[ms]=Ejen Kunci SSH +Name[nb]=SSH-nøkkelagent +Name[nl]=SSH-sleutelagent +Name[nn]=Nøkkelagent for SSH +Name[oc]=Agent de claus SSH +Name[or]=SSH କି ସଦସ୍ୟ +Name[pa]=SSH ਕੁੰਜੀ ਏਜੰਟ +Name[pl]=Agent kluczy SSH +Name[pt]=Agente de chaves SSH +Name[pt_BR]=Agente de chaves SSH +Name[ro]=Agent pentru chei SSH +Name[ru]=Агент ключей SSH +Name[sk]=Agent kľúčov SSH +Name[sl]=Agent ključev SSH +Name[sr]=Агент за ССХ кључеве +Name[sr@latin]=Agent za SSH ključeve +Name[sv]=SSH-nyckelagent +Name[ta]=SSH முகவர் +Name[te]=SSH కీ వాహకము +Name[th]=เอเจนต์กุญแจ SSH +Name[tr]=SSH Anahtar Aracı +Name[ug]=SSH ئاچقۇچ ياردەمچىسى +Name[uk]=Агент ключів SSH +Name[vi]=Đại diện khóa SSH +Name[zh_CN]=SSH 密钥代理 +Name[zh_HK]=SSH 密碼匙代理程式 +Name[zh_TW]=SSH 金鑰代理程式 +Name=SSH Key Agent +Comment[af]=GNOME-sleutelring: SSH-agent +Comment[ar]=حلقة مفاتيح جنوم: عميل SSH +Comment[as]=GNOME Keyring: SSH সহায়ক +Comment[ast]=Depósitu de claves de GNOME: axente SSH +Comment[be]=Вязкі ключоў GNOME: SSH-агент +Comment[bg]=Ключодържател на GNOME: агент на SSH +Comment[bn]=GNOME কী রিং: SSH এজেন্ট +Comment[bn_IN]=GNOME Keyring: SSH এজেন্ট +Comment[bs]=Gnomovi privjesci: SSH agent +Comment[ca]=Anell de claus del GNOME: agent SSH +Comment[ca@valencia]=Anell de claus del GNOME: agent SSH +Comment[cs]=Klíčenka GNOME: Agent SSH +Comment[da]=GNOME-nøgleringsdæmon: SSH-agent +Comment[de]=GNOME-Schlüsselbunddienst: SSH-Agent +Comment[el]=Κλειδοθήκη GNOME: Πράκτορας SSH +Comment[en_GB]=GNOME Keyring: SSH Agent +Comment[eo]=GNOME Ŝlosilaro: SSH-agento +Comment[es]=Depósito de claves de GNOME: agente SSH +Comment[et]=GNOME võtmerõngas: SSH-agent +Comment[eu]=GNOMEren gako-sorta: SSH agentea +Comment[fa]=دسته‌کلید گنوم: عامل SSH +Comment[fi]=Gnomen avainnippu: SSH-agentti +Comment[fr]=Trousseau de clés de GNOME : agent SSH +Comment[fur]=Puarteclâfs di GNOME: agjent SSH +Comment[gd]=Dul-iuchrach: Àidseant SSH +Comment[gl]=GNOME Keyring: Axente SSH +Comment[gu]=GNOME કીરીંગ: SSH ઍજન્ટ +Comment[he]=קבוצת מפתחות של GNOME: סוכן SSH +Comment[hi]=गनोम कीरिंग: SSH प्रतिनिधि +Comment[hr]=GNOME skup ključeva: SSH agent +Comment[hu]=GNOME kulcstartó – SSH-ügynök +Comment[id]=Ring Kunci GNOME: Agen SSH +Comment[it]=Portachiavi di GNOME: agente SSH +Comment[ja]=GNOME キーリング: SSH エージェント +Comment[kk]=GNOME Keyring: SSH агенті +Comment[km]=GNOME Keyring ៖ ភ្នាក់ងារ SSH +Comment[kn]=GNOME ಕೀಲಿಗೊಂಚಲು: SSH ಮಧ್ಯವರ್ತಿ +Comment[ko]=그놈 키 모음: SSH 에이전트 +Comment[lt]=GNOME raktinė: SSH tarnyba +Comment[lv]=GNOME atslēgu saišķis — SSH aģents +Comment[mjw]=GNOME Keyring: SSH Agent +Comment[mk]=Приврзок на GNOME: SSH агент +Comment[ml]=ഗ്നോം കീറിങ്: എസ്എസ്എച് ഏജന്റ് +Comment[mr]=GNOME किरिंग: SSH एजंट +Comment[ms]=Gelang Kunci GNOME: Ejen SSH +Comment[nb]=GNOME nøkkelring: SSH-agent +Comment[ne]=जिनोम किरिङ : SSH एजेन्ट +Comment[nl]=Sleutelbos-service: SSH-agent +Comment[nn]=GNOME Nøkkelring: SSH-agent +Comment[oc]=Trossèl de claus GNOME : agent SSH +Comment[or]=GNOME କି ରିଙ୍ଗ: SSH ସଦସ୍ୟ +Comment[pa]=ਗਨੋਮ ਕੀਰਿੰਗ: SSH ਏਜੰਟ +Comment[pl]=Baza kluczy dla środowiska GNOME: agent SSH +Comment[pt]=GNOME Keyring: agente SSH +Comment[pt_BR]=Chaveiro do GNOME: Agente SSH +Comment[ro]=Inelul de chei GNOME: Agent SSH +Comment[ru]=Связка ключей GNOME: SSH-агент +Comment[sk]=SSH agent zväzku kľúčov GNOME +Comment[sl]=Zbirka ključev GNOME: agent SSH +Comment[sr]=Гномови привесци: ССХ агент +Comment[sr@latin]=Gnomovi privesci: SSH agent +Comment[sv]=GNOME-nyckelring: SSH-agent +Comment[ta]=GNOME கீரிங்: SSH முகவர் +Comment[te]=GNOME కీరింగ్: SSH వాహకం +Comment[th]=พวงกุญแจของ GNOME: เอเจนต์ SSH +Comment[tr]=GNOME Anahtarlığı: SSH Aracı +Comment[ug]=گىنوم ئاچقۇچ ھالقىسى:SSH ياردەمچىسى +Comment[uk]=Служба в'язки ключів GNOME: агент SSH +Comment[vi]=Chùm chìa khóa GNOME: Đại diện SSH +Comment[zh_CN]=GNOME 密钥环:SSH 代理 +Comment[zh_HK]=GNOME 密碼匙圈:SSH 代理程式 +Comment[zh_TW]=GNOME 鑰匙圈:SSH 代理程式 +Comment=GNOME Keyring: SSH Agent +Exec=/usr/bin/gnome-keyring-daemon --start --components=ssh +OnlyShowIn=GNOME;Unity;MATE; +X-GNOME-Autostart-Phase=PreDisplayServer +X-GNOME-AutoRestart=false +X-GNOME-Autostart-Notify=true +X-GNOME-Bugzilla-Bugzilla=GNOME +X-GNOME-Bugzilla-Product=gnome-keyring +X-GNOME-Bugzilla-Component=general +X-GNOME-Bugzilla-Version=42.1 diff --git a/configs/user-tmpfiles.d/discord-rpc.conf b/configs/user-tmpfiles.d/discord-rpc.conf new file mode 100644 index 0000000..031fc68 --- /dev/null +++ b/configs/user-tmpfiles.d/discord-rpc.conf @@ -0,0 +1 @@ +L %t/discord-ipc-0 - - - - app/com.discordapp.Discord/discord-ipc-0 \ No newline at end of file diff --git a/configs/zsh/.zshrc b/configs/zsh/.zshrc index 76704df..60015ff 100644 --- a/configs/zsh/.zshrc +++ b/configs/zsh/.zshrc @@ -37,13 +37,6 @@ if type -p nvim > /dev/null; then export MANWIDTH=80 fi -# Replace gnome-keyring with default ssh agent if possible -if [[ "$HOSTNAME" == "ewpratten-laptop" ]]; then - if type -p gnome-keyring-daemon > /dev/null; then - killall gnome-keyring-daemon 2> /dev/null && eval `ssh-agent` - fi -fi - # SDKMAN! export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" diff --git a/install.conf.yaml b/install.conf.yaml index 17c0203..493e34d 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -54,6 +54,8 @@ # ~/.local/share/remmina: configs/remmina/hosts ~/.cargo/config.toml: configs/cargo/config.toml ~/.config/termux/termux.properties: configs/termux/termux.properties + ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf + ~/.config/autostart/gnome-keyring-ssh.desktop: configs/autostart/gnome-keyring-ssh.desktop - shell: - [git submodule update --init --recursive, Installing submodules] From bbbab9a77162139c6ea02632e7b76d01c60bef09 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 6 Aug 2023 11:58:47 -0400 Subject: [PATCH 099/326] Add mouse config --- configs/logid/logid.cfg | 53 +++++++++++++++++++++++++++++++++++++++++ install.conf.yaml | 2 ++ 2 files changed, 55 insertions(+) create mode 100644 configs/logid/logid.cfg diff --git a/configs/logid/logid.cfg b/configs/logid/logid.cfg new file mode 100644 index 0000000..dba6ee8 --- /dev/null +++ b/configs/logid/logid.cfg @@ -0,0 +1,53 @@ +devices: ( + { + name: "M720 Triathlon Multi-Device Mouse", + hiresscroll: { + hires: true, + invert: false, + target: false + }, + dpi: 1000, + + buttons: ( + # Back + { + cid: 0x53, + action: { + type: "None" + } + }, + + # Forward + { + cid: 0x56, + action: { + type: "None" + } + }, + + # Left Scroll + { + cid: 0x5b, + action: { + type: "None" + } + }, + + # Right Scroll + { + cid: 0x5d, + action: { + type: "None" + } + }, + + # Squeeze + { + cid: 0xd0, + action: { + type: "None" + } + }, + ) + } +); \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index 493e34d..f334b46 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -15,6 +15,7 @@ # Config dirs - ~/.config/nvim - ~/.config/termux + - ~/.config/logid - ~/.cargo # Program plugins - ~/.local/share/nautilus/scripts/ @@ -56,6 +57,7 @@ ~/.config/termux/termux.properties: configs/termux/termux.properties ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf ~/.config/autostart/gnome-keyring-ssh.desktop: configs/autostart/gnome-keyring-ssh.desktop + ~/.config/logid/logid.cfg: configs/logid/logid.cfg - shell: - [git submodule update --init --recursive, Installing submodules] From 50943bb3064f49bf37efd98f3ee0bae112888f3a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 6 Aug 2023 12:06:05 -0400 Subject: [PATCH 100/326] Map middle mouse --- configs/logid/logid.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/logid/logid.cfg b/configs/logid/logid.cfg index dba6ee8..1e50b69 100644 --- a/configs/logid/logid.cfg +++ b/configs/logid/logid.cfg @@ -29,7 +29,8 @@ devices: ( { cid: 0x5b, action: { - type: "None" + type: "Keypress", + keys: [ "BTN_MIDDLE" ] } }, From 997f65a72f52bd52c64991c8a46cba635cf45e85 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 6 Aug 2023 12:10:07 -0400 Subject: [PATCH 101/326] A temp way to solve a vscode bug --- configs/ssh/config | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index 00d93bd..3aecff3 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -1,15 +1,18 @@ # Global Rules -Host * +Host * !*.github.com !github.com IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_rsa -Host * !*.github.com !github.com VisualHostKey yes # Github SSH adapter for restricted networks Host github.com gist.github.com HostName ssh.github.com Port 443 + # This solves a VSCode bug + IdentityFile %d/.ssh/id_ed25519 + IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 + IdentityFile %d/.ssh/id_rsa # Home network Host unifi From d2431d26795019a955bd53f51bf18ca22f64ec60 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 7 Aug 2023 11:52:45 -0400 Subject: [PATCH 102/326] Logid startup --- configs/autostart/logid.desktop | 7 +++++++ configs/scripts/run-logid | 4 ++++ configs/systemd/user/logid.service | 20 ++++++++++++++++++++ install.conf.yaml | 12 +++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 configs/autostart/logid.desktop create mode 100644 configs/scripts/run-logid create mode 100644 configs/systemd/user/logid.service diff --git a/configs/autostart/logid.desktop b/configs/autostart/logid.desktop new file mode 100644 index 0000000..d8ae2a7 --- /dev/null +++ b/configs/autostart/logid.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name = Logid +GenericName = Logid +Comment = Logitech Mouse Driver +Exec = logid -v -c $HOME/.config/logid/logid.cfg +Type = Application +X-GNOME-Autostart-enabled = true diff --git a/configs/scripts/run-logid b/configs/scripts/run-logid new file mode 100644 index 0000000..9c2720b --- /dev/null +++ b/configs/scripts/run-logid @@ -0,0 +1,4 @@ +#! /bin/bash +set -ex + +logid -v -c ~/.config/logid/logid.cfg diff --git a/configs/systemd/user/logid.service b/configs/systemd/user/logid.service new file mode 100644 index 0000000..707f9f9 --- /dev/null +++ b/configs/systemd/user/logid.service @@ -0,0 +1,20 @@ +# NOTE: In order to use this service, the following needs to be placed in +# /etc/udev/rules.d/90-hidraw-permissions.rules +# +# KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0664", GROUP="plugdev" +# +# This can then be put into effect with: +# sudo udevadm control --reload-rules && sudo udevadm trigger + +[Unit] +Description = Logitech mouse driver + +[Service] +Type = simple +User = ewpratten +#Group = plugdev +ExecStart = logid -v -c /home/ewpratten/.config/logid/logid.cfg +Restart = always + +[Install] +WantedBy = multi-user.target diff --git a/install.conf.yaml b/install.conf.yaml index f334b46..31ce75a 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -16,6 +16,7 @@ - ~/.config/nvim - ~/.config/termux - ~/.config/logid + - ~/.config/systemd/user - ~/.cargo # Program plugins - ~/.local/share/nautilus/scripts/ @@ -48,6 +49,16 @@ ~/.local/share/nautilus/scripts/Copy to web: path: configs/nautilus/scripts/Copy to web mode: 755 + ~/bin/run-logid: + path: configs/scripts/run-logid + mode: 755 + + # Systemd Services + # ~/.config/systemd/user/logid.service: configs/systemd/user/logid.service + + # XDG Autostart + ~/.config/autostart/gnome-keyring-ssh.desktop: configs/autostart/gnome-keyring-ssh.desktop + ~/.config/autostart/logid.desktop: configs/autostart/logid.desktop # Others ~/.config/tabset: configs/tabset @@ -56,7 +67,6 @@ ~/.cargo/config.toml: configs/cargo/config.toml ~/.config/termux/termux.properties: configs/termux/termux.properties ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf - ~/.config/autostart/gnome-keyring-ssh.desktop: configs/autostart/gnome-keyring-ssh.desktop ~/.config/logid/logid.cfg: configs/logid/logid.cfg - shell: From 4ed7e2d67c5a668e2537bdcacdccc6f1730c1a70 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 7 Aug 2023 11:59:16 -0400 Subject: [PATCH 103/326] Move xareo waypoints to common location --- .../Multiplayer_mc.sdf.org/config.txt | 13 +++++ .../dim%0/mw$default_1.txt | 48 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt create mode 100644 configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt diff --git a/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt b/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt new file mode 100644 index 0000000..bc89407 --- /dev/null +++ b/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt @@ -0,0 +1,13 @@ +//waypoints config options +usingMultiworldDetection:false +ignoreServerLevelId:false +defaultMultiworldId:mw-3,1,-4 +teleportationEnabled:true +usingDefaultTeleportCommand:false +serverTeleportCommandFormat:^col^warp add {x},{y},{z} +serverTeleportCommandRotationFormat:^col^warp add {x},{y},{z} +sortType:NONE +sortReversed:false + +//other config options +ignoreHeightmaps:false diff --git a/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt b/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt new file mode 100644 index 0000000..6bd0792 --- /dev/null +++ b/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt @@ -0,0 +1,48 @@ +sets:Subway Stations:gui.xaero_default +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:visibility_type:destination +# +waypoint:Spawn Glider Port Station:S:-219:97:-254:12:false:0:Subway Stations:false:0:0:false +waypoint:Bell Bridge / Changa Station:S:-219:97:-375:12:false:0:Subway Stations:false:0:0:false +waypoint:Eccentric Genius Station:S:-219:96:-481:12:false:0:Subway Stations:false:0:0:false +waypoint:Xiled Station:S:-219:97:-552:12:false:0:Subway Stations:false:0:0:false +waypoint:Nopantsistan Station:S:-219:98:-650:12:false:0:Subway Stations:false:0:0:false +waypoint:[HLV] Highland Village Station:S:-220:97:-1797:12:false:0:Subway Stations:false:0:0:false +waypoint:[MSW] Mid-Swamp Station:S:-187:41:-1254:14:false:0:Subway Stations:false:0:0:false +waypoint:[JOT] Jotaku Station:S:-187:42:-782:14:false:0:Subway Stations:false:0:0:false +waypoint:[NSX] Northside Transfer Station:S:-197:42:-719:13:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Central Station:S:-217:56:-275:6:false:0:Subway Stations:false:0:0:false +waypoint:[NRV] North River Station:S:-245:38:-366:13:false:0:Subway Stations:false:0:0:false +waypoint:[CMK] Central Market Station:S:-245:38:-258:13:false:0:Subway Stations:false:0:0:false +waypoint:Monument Place Station:S:-219:35:-137:13:false:0:Subway Stations:false:0:0:false +waypoint:Monument Place Station:S:-220:43:-137:10:false:0:Subway Stations:false:0:0:false +waypoint:Survey Hall Station:S:-120:59:-481:10:false:0:Subway Stations:false:0:0:false +waypoint:Inventory Station:S:-143:43:-304:10:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Square Station:S:-115:53:-256:10:false:0:Subway Stations:false:0:0:false +waypoint:Tek Square Station:S:63:65:-215:9:false:0:Subway Stations:false:0:0:false +waypoint:Manor Ave Station:S:-36:58:-225:9:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Square Station:S:-141:58:-225:9:false:0:Subway Stations:false:0:0:false +waypoint:DOJO St Station:S:-221:56:-226:9:false:0:Subway Stations:false:0:0:false +waypoint:Mob St Station:S:-389:64:-222:9:false:0:Subway Stations:false:0:0:false +waypoint:[CAT] Cat Ave Station:S:-491:64:-222:9:false:0:Subway Stations:false:0:0:false +waypoint:Garfield Station:S:-624:73:310:8:false:0:Subway Stations:false:0:0:false +waypoint:Castle Square Station:S:-616:61:-222:8:false:0:Subway Stations:false:0:0:false +waypoint:[CHA] Changa Station:S:-187:42:-373:14:false:0:Subway Stations:false:0:0:false +waypoint:[ECG] Eccentric Genius:S:-187:42:-477:14:false:0:Subway Stations:false:0:0:false +waypoint:[XIL] Xiled Station:S:-187:42:-575:14:false:0:Subway Stations:false:0:0:false +waypoint:[NOP] Nopantsistan Station:S:-187:42:-662:14:false:0:Subway Stations:false:0:0:false +waypoint:[NSX] Northside Transfer:S:-187:42:-720:14:false:0:Subway Stations:false:0:0:false +waypoint:[NPN] Nopantsistan Station:S:-245:38:-665:13:false:0:Subway Stations:false:0:0:false +waypoint:[LAY] Laydros Station:S:-245:38:-543:13:false:0:Subway Stations:false:0:0:false +waypoint:Red Station:S:-900:109:-1992:8:false:0:Subway Stations:false:0:0:false +waypoint:[NSC] North Shore City Terminal:S:-72:42:-1946:14:false:0:Subway Stations:false:0:0:false +waypoint:[NSJ] North Shore Junction:J:-183:39:-1949:8:false:0:Subway Stations:false:0:0:false +waypoint:[HLV] Highland Village Station:S:-187:41:-1736:14:false:0:Subway Stations:false:0:0:false +waypoint:[NDK] North Docks Station:S:-187:41:-1519:14:false:0:Subway Stations:false:0:0:false +waypoint:[BOH] Boathouse Station:S:-187:42:-839:14:false:0:Subway Stations:false:0:0:false +waypoint:[RST] Riverside Station:S:-189:42:-321:14:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Central Station:S:-213:42:-258:8:false:0:Subway Stations:false:0:0:false +waypoint:End Portal:E:921:23:1221:5:false:0:gui.xaero_default:false:0:0:false +waypoint:Miwu Home:M:-287:77:-432:9:false:0:gui.xaero_default:false:0:0:false +waypoint:Home:H:-198:69:-303:9:false:0:gui.xaero_default:false:0:1:false +waypoint:Spawn:*:-137:70:-256:0:false:0:gui.xaero_default:false:0:1:false From d7ece7ffea4ce9039c93c5795a70bdb9bd2a8275 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 7 Aug 2023 12:02:47 -0400 Subject: [PATCH 104/326] Fix naming --- .../minimap/waypoints/Multiplayer_mc.sdf.org/config.txt | 0 .../waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt | 0 install.conf.yaml | 1 + 3 files changed, 1 insertion(+) rename configs/{xareo => xaero}/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt (100%) rename configs/{xareo => xaero}/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt (100%) diff --git a/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt b/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt similarity index 100% rename from configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt rename to configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt diff --git a/configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt b/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt similarity index 100% rename from configs/xareo/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt rename to configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt diff --git a/install.conf.yaml b/install.conf.yaml index 31ce75a..3a5a0c6 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -68,6 +68,7 @@ ~/.config/termux/termux.properties: configs/termux/termux.properties ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf ~/.config/logid/logid.cfg: configs/logid/logid.cfg + ~/.config/xaero: configs/xaero - shell: - [git submodule update --init --recursive, Installing submodules] From b54d16fd6ed7289a571dbabf7750d0cc15581182 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 7 Aug 2023 12:09:48 -0400 Subject: [PATCH 105/326] undo --- .../Multiplayer_mc.sdf.org/config.txt | 13 ----- .../dim%0/mw$default_1.txt | 48 ------------------- install.conf.yaml | 1 - 3 files changed, 62 deletions(-) delete mode 100644 configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt delete mode 100644 configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt diff --git a/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt b/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt deleted file mode 100644 index bc89407..0000000 --- a/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/config.txt +++ /dev/null @@ -1,13 +0,0 @@ -//waypoints config options -usingMultiworldDetection:false -ignoreServerLevelId:false -defaultMultiworldId:mw-3,1,-4 -teleportationEnabled:true -usingDefaultTeleportCommand:false -serverTeleportCommandFormat:^col^warp add {x},{y},{z} -serverTeleportCommandRotationFormat:^col^warp add {x},{y},{z} -sortType:NONE -sortReversed:false - -//other config options -ignoreHeightmaps:false diff --git a/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt b/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt deleted file mode 100644 index 6bd0792..0000000 --- a/configs/xaero/minimap/waypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt +++ /dev/null @@ -1,48 +0,0 @@ -sets:Subway Stations:gui.xaero_default -# -#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:visibility_type:destination -# -waypoint:Spawn Glider Port Station:S:-219:97:-254:12:false:0:Subway Stations:false:0:0:false -waypoint:Bell Bridge / Changa Station:S:-219:97:-375:12:false:0:Subway Stations:false:0:0:false -waypoint:Eccentric Genius Station:S:-219:96:-481:12:false:0:Subway Stations:false:0:0:false -waypoint:Xiled Station:S:-219:97:-552:12:false:0:Subway Stations:false:0:0:false -waypoint:Nopantsistan Station:S:-219:98:-650:12:false:0:Subway Stations:false:0:0:false -waypoint:[HLV] Highland Village Station:S:-220:97:-1797:12:false:0:Subway Stations:false:0:0:false -waypoint:[MSW] Mid-Swamp Station:S:-187:41:-1254:14:false:0:Subway Stations:false:0:0:false -waypoint:[JOT] Jotaku Station:S:-187:42:-782:14:false:0:Subway Stations:false:0:0:false -waypoint:[NSX] Northside Transfer Station:S:-197:42:-719:13:false:0:Subway Stations:false:0:0:false -waypoint:Spawn Central Station:S:-217:56:-275:6:false:0:Subway Stations:false:0:0:false -waypoint:[NRV] North River Station:S:-245:38:-366:13:false:0:Subway Stations:false:0:0:false -waypoint:[CMK] Central Market Station:S:-245:38:-258:13:false:0:Subway Stations:false:0:0:false -waypoint:Monument Place Station:S:-219:35:-137:13:false:0:Subway Stations:false:0:0:false -waypoint:Monument Place Station:S:-220:43:-137:10:false:0:Subway Stations:false:0:0:false -waypoint:Survey Hall Station:S:-120:59:-481:10:false:0:Subway Stations:false:0:0:false -waypoint:Inventory Station:S:-143:43:-304:10:false:0:Subway Stations:false:0:0:false -waypoint:Spawn Square Station:S:-115:53:-256:10:false:0:Subway Stations:false:0:0:false -waypoint:Tek Square Station:S:63:65:-215:9:false:0:Subway Stations:false:0:0:false -waypoint:Manor Ave Station:S:-36:58:-225:9:false:0:Subway Stations:false:0:0:false -waypoint:Spawn Square Station:S:-141:58:-225:9:false:0:Subway Stations:false:0:0:false -waypoint:DOJO St Station:S:-221:56:-226:9:false:0:Subway Stations:false:0:0:false -waypoint:Mob St Station:S:-389:64:-222:9:false:0:Subway Stations:false:0:0:false -waypoint:[CAT] Cat Ave Station:S:-491:64:-222:9:false:0:Subway Stations:false:0:0:false -waypoint:Garfield Station:S:-624:73:310:8:false:0:Subway Stations:false:0:0:false -waypoint:Castle Square Station:S:-616:61:-222:8:false:0:Subway Stations:false:0:0:false -waypoint:[CHA] Changa Station:S:-187:42:-373:14:false:0:Subway Stations:false:0:0:false -waypoint:[ECG] Eccentric Genius:S:-187:42:-477:14:false:0:Subway Stations:false:0:0:false -waypoint:[XIL] Xiled Station:S:-187:42:-575:14:false:0:Subway Stations:false:0:0:false -waypoint:[NOP] Nopantsistan Station:S:-187:42:-662:14:false:0:Subway Stations:false:0:0:false -waypoint:[NSX] Northside Transfer:S:-187:42:-720:14:false:0:Subway Stations:false:0:0:false -waypoint:[NPN] Nopantsistan Station:S:-245:38:-665:13:false:0:Subway Stations:false:0:0:false -waypoint:[LAY] Laydros Station:S:-245:38:-543:13:false:0:Subway Stations:false:0:0:false -waypoint:Red Station:S:-900:109:-1992:8:false:0:Subway Stations:false:0:0:false -waypoint:[NSC] North Shore City Terminal:S:-72:42:-1946:14:false:0:Subway Stations:false:0:0:false -waypoint:[NSJ] North Shore Junction:J:-183:39:-1949:8:false:0:Subway Stations:false:0:0:false -waypoint:[HLV] Highland Village Station:S:-187:41:-1736:14:false:0:Subway Stations:false:0:0:false -waypoint:[NDK] North Docks Station:S:-187:41:-1519:14:false:0:Subway Stations:false:0:0:false -waypoint:[BOH] Boathouse Station:S:-187:42:-839:14:false:0:Subway Stations:false:0:0:false -waypoint:[RST] Riverside Station:S:-189:42:-321:14:false:0:Subway Stations:false:0:0:false -waypoint:Spawn Central Station:S:-213:42:-258:8:false:0:Subway Stations:false:0:0:false -waypoint:End Portal:E:921:23:1221:5:false:0:gui.xaero_default:false:0:0:false -waypoint:Miwu Home:M:-287:77:-432:9:false:0:gui.xaero_default:false:0:0:false -waypoint:Home:H:-198:69:-303:9:false:0:gui.xaero_default:false:0:1:false -waypoint:Spawn:*:-137:70:-256:0:false:0:gui.xaero_default:false:0:1:false diff --git a/install.conf.yaml b/install.conf.yaml index 3a5a0c6..31ce75a 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -68,7 +68,6 @@ ~/.config/termux/termux.properties: configs/termux/termux.properties ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf ~/.config/logid/logid.cfg: configs/logid/logid.cfg - ~/.config/xaero: configs/xaero - shell: - [git submodule update --init --recursive, Installing submodules] From 52da6b88c9a3a45314b9937fd1095f01b47cd2af Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 9 Aug 2023 12:57:41 -0400 Subject: [PATCH 106/326] Add a keybind for launching a python repl --- configs/gnome/desktop-settings.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index b1717dd..c0867be 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -41,7 +41,7 @@ gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['4 keybindings=$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings) if [ "$keybindings" = "[]" ] || [ "$keybindings" = "@as []" ]; then # Define the list of custom keybindings - gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/']" + gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/' , '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/']" # Allow Mod+Enter to open a terminal gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/ name "Terminal" @@ -52,6 +52,11 @@ if [ "$keybindings" = "[]" ] || [ "$keybindings" = "@as []" ]; then gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ name "Rofi" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ command "rofi -show drun" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ binding "d" + + # Allow Mod+Shift+Enter to open python + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/ name "Python REPL" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/ command "gnome-terminal -- python3" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/ binding "Return" fi # Top Bar settings From f8dea523743b77634ae8934b0ec08a7d53df4e94 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 21 Aug 2023 09:49:30 -0400 Subject: [PATCH 107/326] Disable logid for now --- configs/autostart/logid.desktop | 2 +- configs/systemd/user/logid.service | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 configs/systemd/user/logid.service diff --git a/configs/autostart/logid.desktop b/configs/autostart/logid.desktop index d8ae2a7..acaaf24 100644 --- a/configs/autostart/logid.desktop +++ b/configs/autostart/logid.desktop @@ -4,4 +4,4 @@ GenericName = Logid Comment = Logitech Mouse Driver Exec = logid -v -c $HOME/.config/logid/logid.cfg Type = Application -X-GNOME-Autostart-enabled = true +X-GNOME-Autostart-enabled = false diff --git a/configs/systemd/user/logid.service b/configs/systemd/user/logid.service deleted file mode 100644 index 707f9f9..0000000 --- a/configs/systemd/user/logid.service +++ /dev/null @@ -1,20 +0,0 @@ -# NOTE: In order to use this service, the following needs to be placed in -# /etc/udev/rules.d/90-hidraw-permissions.rules -# -# KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0664", GROUP="plugdev" -# -# This can then be put into effect with: -# sudo udevadm control --reload-rules && sudo udevadm trigger - -[Unit] -Description = Logitech mouse driver - -[Service] -Type = simple -User = ewpratten -#Group = plugdev -ExecStart = logid -v -c /home/ewpratten/.config/logid/logid.cfg -Restart = always - -[Install] -WantedBy = multi-user.target From b42bdfdf740d54ffc6209706d3a8ab2eaeb8b1fa Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 11 Sep 2023 13:49:04 -0400 Subject: [PATCH 108/326] Update how nvim handles diffs --- configs/git/.gitconfig | 2 +- configs/nvim/init.vim | 11 ++++++++++- configs/ssh/config | 4 ++++ configs/zsh/macros.sh | 1 + install.conf.yaml | 6 ++++++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 700f478..ce86ee2 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -16,7 +16,7 @@ detachedHead = true [alias] - authors = shortlog --summary --numbered --email + authors = shortlog --summary --numbered --email [filter "lfs"] clean = git-lfs clean -- %f diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 2215d24..0768444 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -70,10 +70,19 @@ if !exists('g:vscode') hi clear SpellCap hi clear SpellRare - " Disable spellcheck for manpages + " Disable spellcheck for some file formats autocmd FileType man setlocal nospell + autocmd FileType diff setlocal nospell endif +" Configure Diff rendering +hi DiffText ctermfg=White ctermbg=none +hi DiffFile ctermfg=White ctermbg=none cterm=bold +hi DiffIndexLine ctermfg=White ctermbg=none cterm=bold +hi DiffAdd ctermfg=DarkGreen ctermbg=none +hi DiffChange ctermfg=DarkRed ctermbg=none +hi DiffDelete ctermfg=DarkRed ctermbg=none + " Disable the gitgutter background let g:gitgutter_override_sign_column_highlight = 1 highlight clear SignColumn diff --git a/configs/ssh/config b/configs/ssh/config index 3aecff3..85669c3 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -71,6 +71,10 @@ Host *.ring.nlnog.net Host sdf.org *.sdf.org user ewpratten +# Guru +Host *.gurustudio.com + User "guru-domain\\epratten" + # Personal Infra Host oci-arm HostName oci-arm.ip.ewp.fyi diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 4bc77e9..fc68396 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -11,6 +11,7 @@ alias flush-dns="sudo systemd-resolve --flush-caches" alias showsizes="du -h --max-depth=1" alias lsgrep="ls | grep" alias sheridan-rdp='firefox --new-window "ext+container:name=College&url=https://client.wvd.microsoft.com/arm/webclient/index.html"' +alias git-diff-nvim="git diff | nvim -R -d -c 'set filetype=diff' -" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" diff --git a/install.conf.yaml b/install.conf.yaml index 31ce75a..5a437b2 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -70,11 +70,17 @@ ~/.config/logid/logid.cfg: configs/logid/logid.cfg - shell: + # Make sure we have our git modules - [git submodule update --init --recursive, Installing submodules] + # Install SSH config - [sh ./helpers/install-ssh-config.sh, Installing SSH config] + # Ensure that all downloaded scripts are executable - [chmod +x configs/scripts/catto, Making catto executable] - [chmod +x configs/scripts/aspath, Making aspath executable] - [chmod +x configs/scripts/fetch-steamdeck-screenshots, Making fetch-steamdeck-screenshots executable] + # Configure GNOME - [sh ./helpers/configure-gnome.sh, Configuring GNOME] + # Configure Termux if on Android - [termux-reload-settings || true, Trying to reload Termux] + # Configure Git - [bash ./helpers/git-config-features.sh, Setting up optional git-config features] From 9c91c046a240944082680615f69ab1d18e82bcd6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 13 Sep 2023 16:06:03 -0400 Subject: [PATCH 109/326] Add a macro for generating TOTP codes from an attached YubiKey --- configs/zsh/macros.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index fc68396..d523e58 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -12,6 +12,7 @@ alias showsizes="du -h --max-depth=1" alias lsgrep="ls | grep" alias sheridan-rdp='firefox --new-window "ext+container:name=College&url=https://client.wvd.microsoft.com/arm/webclient/index.html"' alias git-diff-nvim="git diff | nvim -R -d -c 'set filetype=diff' -" +alias yk-totp="ykman oath accounts code" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" @@ -135,4 +136,4 @@ wg-reload() { else wg syncconf $1 <(wg-quick strip $1) fi -} \ No newline at end of file +} From 59a15a617755bb7866ee830fa34abeea5cf336e0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 28 Sep 2023 13:05:56 -0400 Subject: [PATCH 110/326] Add video trimmer script --- .../nautilus/scripts/Open in Video Trimmer | 4 + configs/scripts/video_trimmer.py | 242 ++++++++++++++++++ install.conf.yaml | 4 + 3 files changed, 250 insertions(+) create mode 100755 configs/nautilus/scripts/Open in Video Trimmer create mode 100755 configs/scripts/video_trimmer.py diff --git a/configs/nautilus/scripts/Open in Video Trimmer b/configs/nautilus/scripts/Open in Video Trimmer new file mode 100755 index 0000000..2839891 --- /dev/null +++ b/configs/nautilus/scripts/Open in Video Trimmer @@ -0,0 +1,4 @@ +#! /bin/bash +set -e + +python3 ~/.config/ewconfig/configs/scripts/video_trimmer.py \ No newline at end of file diff --git a/configs/scripts/video_trimmer.py b/configs/scripts/video_trimmer.py new file mode 100755 index 0000000..659060d --- /dev/null +++ b/configs/scripts/video_trimmer.py @@ -0,0 +1,242 @@ +#! /usr/bin/env python3 +import os +import argparse +import sys +import re +import datetime +import subprocess +import tkinter as tk +from pathlib import Path + +ALLOWED_INPUT_FORMATS = ["mp4"] +TIMESTAMP_FORMAT_RE = re.compile(r"^\d{2}:\d{2}:\d{2}$") +RENDER_MODES = ["Video + Audio", "Video Only", "Audio Only"] + + +def open_in_video_player(file: Path): + os.system(f"xdg-open {file}") + + +def render( + input_file: Path, + output_file: Path, + start_timestamp: str, + end_timestamp: str, + mode: str, +): + # Construct the appropriate ffmpeg command + ffmpeg_command = ["ffmpeg"] + + # Add the input file + ffmpeg_command += ["-i", str(input_file)] + + # Add the start and end timestamps + ffmpeg_command += ["-ss", start_timestamp] + ffmpeg_command += ["-to", end_timestamp] + + # Add the mode + if mode == "Video + Audio": + ffmpeg_command += ["-c", "copy"] + elif mode == "Video Only": + ffmpeg_command += ["-c", "copy"] + ffmpeg_command += ["-an"] + elif mode == "Audio Only": + ffmpeg_command += ["-vn"] + + # Add the output file + ffmpeg_command += [str(output_file)] + + # Run the command. Open in a new terminal window + subprocess.call(ffmpeg_command) + + +def do_preview(input_file: Path, start_timestamp: str, end_timestamp: str, mode: str): + # Start by rendering to a tempfile with the same extension as the input file + temp_file = Path("/tmp") / f"{input_file.stem}_trimmed{input_file.suffix}" + temp_file.unlink(missing_ok=True) + render(input_file, temp_file, start_timestamp, end_timestamp, mode) + + # Display the temp file in a video player + open_in_video_player(temp_file) + + +def do_render(input_file: Path, start_timestamp: str, end_timestamp: str, mode: str): + # Create the new file beside the old one + start_time_str = start_timestamp.replace(":", ".") + end_time_str = end_timestamp.replace(":", ".") + output_file = ( + input_file.parent + / f"{input_file.stem}_trimmed_{start_time_str}_{end_time_str}_render{input_file.suffix}" + ) + output_file.unlink(missing_ok=True) + + # Call the render function + render(input_file, output_file, start_timestamp, end_timestamp, mode) + + # Copy the timestamp metadata from the original file (force overwrite) + subprocess.call(["ffmpeg", "-i", str(input_file), "-i", str(output_file), "-map_metadata", "0", "-map", "0", "-map", "1", "-c", "copy", "-y", str(output_file)]) + + # Set the file timestamp to the same as the original file + subprocess.call(["touch", "-r", str(input_file), str(output_file)]) + + +def build_gui(input_file: Path) -> tk.Tk: + # Build the GUI + root = tk.Tk() + root.title("Evan's Video Trimmer") + # root.geometry("280x500") + + # Add a section title + title = tk.Label(root, text="Input File") + title.grid(row=0, column=0, columnspan=2) + + # Add a button to open the original file + open_original_button = tk.Button( + root, + text="Open original file", + command=lambda: open_in_video_player(input_file), + ) + open_original_button.grid(row=2, column=0, columnspan=2, pady=2) + + # Add a horizontal separator + separator = tk.Frame(height=2, bd=1, relief=tk.SUNKEN) + separator.grid(row=3, column=0, columnspan=2, sticky=tk.W + tk.E, pady=2) + + # Add a section title + title = tk.Label(root, text="Output Controls") + title.grid(row=4, column=0, columnspan=2, pady=2) + + # Add an input field for start timestamp + start_timestamp = tk.StringVar() + start_timestamp.set("00:00:00") + start_timestamp_label = tk.Label(root, text="Start Timestamp") + start_timestamp_label.grid(row=5, column=0, sticky=tk.E) + start_timestamp_input = tk.Entry(root, textvariable=start_timestamp) + start_timestamp_input.grid(row=5, column=1) + + # Add an input field for end timestamp + end_timestamp = tk.StringVar() + end_timestamp.set("00:00:00") + end_timestamp_label = tk.Label(root, text="End Timestamp") + end_timestamp_label.grid(row=6, column=0, sticky=tk.E) + end_timestamp_input = tk.Entry(root, textvariable=end_timestamp) + end_timestamp_input.grid(row=6, column=1) + + # Add a "mode" dropdown + mode = tk.StringVar() + mode.set(RENDER_MODES[0]) + mode_label = tk.Label(root, text="Trim Mode") + mode_label.grid(row=7, column=0, sticky=tk.E) + mode_input = tk.OptionMenu(root, mode, *RENDER_MODES) + mode_input.grid(row=7, column=1, sticky="we") + + # Add a horizontal separator + separator = tk.Frame(height=2, bd=1, relief=tk.SUNKEN) + separator.grid(row=8, column=0, columnspan=2, sticky=tk.W + tk.E, pady=2) + + # Function to pre-validate inputs + def validate_inputs(): + # The start timestamp must be hh:mm:ss + if not TIMESTAMP_FORMAT_RE.match(start_timestamp.get()): + popup_error( + "Start timestamp must be in hh:mm:ss format", quit_on_close=False + ) + return False + # The end timestamp must be hh:mm:ss + if not TIMESTAMP_FORMAT_RE.match(end_timestamp.get()): + popup_error("End timestamp must be in hh:mm:ss format", quit_on_close=False) + return False + # The end timestamp must be after the start timestamp + start_time = datetime.datetime.strptime(start_timestamp.get(), "%H:%M:%S") + end_time = datetime.datetime.strptime(end_timestamp.get(), "%H:%M:%S") + if end_time <= start_time: + popup_error( + "End timestamp must be after start timestamp", quit_on_close=False + ) + return False + return True + + # Add a button to preview the output + preview_button = tk.Button( + root, + text="Preview Output", + command=lambda: do_preview( + input_file, start_timestamp.get(), end_timestamp.get(), mode.get() + ) + if validate_inputs() + else None, + ) + preview_button.grid(row=9, column=0, pady=2, sticky="we") + + # Add a button to render the output + render_button = tk.Button( + root, + text="Render", + command=lambda: do_render( + input_file, start_timestamp.get(), end_timestamp.get(), mode.get() + ) + if validate_inputs() + else None, + ) + render_button.grid(row=9, column=1, pady=2, sticky="we") + + return root + + +def popup_error(message: str, quit_on_close: bool = True): + # Make a popup window + popup = tk.Tk() + popup.wm_title("Error") + + # Add a message + label = tk.Label(popup, text=message) + label.pack(side="top", fill="x", pady=10) + + # Add a button to close the popup + button = tk.Button(popup, text="Okay", command=popup.destroy) + button.pack() + + # Run the popup + popup.mainloop() + + # Exit the program + if quit_on_close: + sys.exit(1) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser() + ap.add_argument( + "--file", help="File to open in Video Trimmer", type=str, required=False + ) + args = ap.parse_args() + + # Read the file + uncut_file = Path(args.file) if args.file else None + if not uncut_file: + # Try to read from env + if "NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" not in os.environ: + popup_error("No file selected") + return 1 + uncut_file = Path( + os.environ["NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"].splitlines()[0] + ) + + # Require one of the acceptable file types + if uncut_file.suffix[1:].lower() not in ALLOWED_INPUT_FORMATS: + popup_error( + f"File type not supported: {uncut_file.suffix}\n" + f"Supported types: {ALLOWED_INPUT_FORMATS}" + ) + return 1 + + # Build the GUI and run + root = build_gui(uncut_file) + root.mainloop() + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/install.conf.yaml b/install.conf.yaml index 5a437b2..8cd76c1 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -49,6 +49,9 @@ ~/.local/share/nautilus/scripts/Copy to web: path: configs/nautilus/scripts/Copy to web mode: 755 + ~/.local/share/nautilus/scripts/Open in Video Trimmer: + path: configs/nautilus/scripts/Open in Video Trimmer + mode: 755 ~/bin/run-logid: path: configs/scripts/run-logid mode: 755 @@ -78,6 +81,7 @@ - [chmod +x configs/scripts/catto, Making catto executable] - [chmod +x configs/scripts/aspath, Making aspath executable] - [chmod +x configs/scripts/fetch-steamdeck-screenshots, Making fetch-steamdeck-screenshots executable] + - [chmod +x configs/nautilus/scripts/*, Making nautilus scripts executable] # Configure GNOME - [sh ./helpers/configure-gnome.sh, Configuring GNOME] # Configure Termux if on Android From b3a8c1ecae6a1d95fe654569fab02c1319e3e86b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 28 Sep 2023 13:25:20 -0400 Subject: [PATCH 111/326] Update nvim plugins --- configs/nvim/pack/airblade/start/vim-gitgutter | 2 +- configs/nvim/pack/ggandor/start/leap.nvim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/nvim/pack/airblade/start/vim-gitgutter b/configs/nvim/pack/airblade/start/vim-gitgutter index 4a7ca06..f7b9766 160000 --- a/configs/nvim/pack/airblade/start/vim-gitgutter +++ b/configs/nvim/pack/airblade/start/vim-gitgutter @@ -1 +1 @@ -Subproject commit 4a7ca061af2b199a9b97041270611439e8fa2b02 +Subproject commit f7b97666ae36c7b3f262f3190dbcd7033845d985 diff --git a/configs/nvim/pack/ggandor/start/leap.nvim b/configs/nvim/pack/ggandor/start/leap.nvim index dabcce4..5efe985 160000 --- a/configs/nvim/pack/ggandor/start/leap.nvim +++ b/configs/nvim/pack/ggandor/start/leap.nvim @@ -1 +1 @@ -Subproject commit dabcce410ea8655f3c0acaee8da8f366b4a629a8 +Subproject commit 5efe985cf68fac3b6a6dfe7a75fbfaca8db2af9c From 0b78e8f57d04fd38400210a40c03a1b47fae8e61 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 28 Sep 2023 14:46:01 -0400 Subject: [PATCH 112/326] Bugfix for files with spaces in their names --- configs/scripts/video_trimmer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/scripts/video_trimmer.py b/configs/scripts/video_trimmer.py index 659060d..98b1843 100755 --- a/configs/scripts/video_trimmer.py +++ b/configs/scripts/video_trimmer.py @@ -14,7 +14,7 @@ RENDER_MODES = ["Video + Audio", "Video Only", "Audio Only"] def open_in_video_player(file: Path): - os.system(f"xdg-open {file}") + os.system(f'xdg-open "{file}"') def render( From 241f1a44d7f256311dd31d07e7f3292c8f359e5e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 28 Sep 2023 15:12:17 -0400 Subject: [PATCH 113/326] Export audio correctly --- configs/scripts/video_trimmer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/scripts/video_trimmer.py b/configs/scripts/video_trimmer.py index 98b1843..36e9186 100755 --- a/configs/scripts/video_trimmer.py +++ b/configs/scripts/video_trimmer.py @@ -64,9 +64,10 @@ def do_render(input_file: Path, start_timestamp: str, end_timestamp: str, mode: # Create the new file beside the old one start_time_str = start_timestamp.replace(":", ".") end_time_str = end_timestamp.replace(":", ".") + file_suffix = ".mp3" if mode == "Audio Only" else input_file.suffix output_file = ( input_file.parent - / f"{input_file.stem}_trimmed_{start_time_str}_{end_time_str}_render{input_file.suffix}" + / f"{input_file.stem}_trimmed_{start_time_str}_{end_time_str}_render{file_suffix}" ) output_file.unlink(missing_ok=True) From ba1a922470f529209a4b7481b15b5bd62ff4fd36 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 5 Oct 2023 19:33:00 -0400 Subject: [PATCH 114/326] Add tools for launching lightly toasted Houdini --- .gitignore | 3 +- .vscode/settings.json | 8 +- configs/houdini19.5/scripts/456.cmd | 1 + configs/scripts/houdini-tool.py | 106 ++++++++++++++ configs/scripts/hython-latest | 9 ++ configs/scripts/run-logid | 0 configs/scripts/usdnc-to-usd.py | 47 +++++++ configs/ssh/config | 2 + install.conf.yaml | 8 +- python_modules/ewpipe/common/dirs.py | 13 ++ python_modules/ewpipe/common/env.py | 31 +++++ python_modules/ewpipe/common/logging.py | 8 ++ python_modules/ewpipe/houdini/editions.py | 36 +++++ .../ewpipe/houdini/installations.py | 129 ++++++++++++++++++ 14 files changed, 395 insertions(+), 6 deletions(-) create mode 100644 configs/houdini19.5/scripts/456.cmd create mode 100755 configs/scripts/houdini-tool.py create mode 100755 configs/scripts/hython-latest mode change 100644 => 100755 configs/scripts/run-logid create mode 100755 configs/scripts/usdnc-to-usd.py create mode 100644 python_modules/ewpipe/common/dirs.py create mode 100644 python_modules/ewpipe/common/env.py create mode 100644 python_modules/ewpipe/common/logging.py create mode 100644 python_modules/ewpipe/houdini/editions.py create mode 100644 python_modules/ewpipe/houdini/installations.py diff --git a/.gitignore b/.gitignore index ef07850..4fb0350 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/configs/remmina \ No newline at end of file +/configs/remmina +__pycache__ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 58d16ed..270f0cd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,10 @@ "*.md.liquid": "markdown", "*.js.liquid": "liquid-javascript", "*.css.liquid": "liquid-css", - "*.scss.liquid": "liquid-scss", - } + "*.scss.liquid": "liquid-scss" + }, + // Add python_modules to the python path + "python.analysis.extraPaths": [ + "./python_modules" + ], } \ No newline at end of file diff --git a/configs/houdini19.5/scripts/456.cmd b/configs/houdini19.5/scripts/456.cmd new file mode 100644 index 0000000..4101639 --- /dev/null +++ b/configs/houdini19.5/scripts/456.cmd @@ -0,0 +1 @@ +preference general.desk.val "Solaris" \ No newline at end of file diff --git a/configs/scripts/houdini-tool.py b/configs/scripts/houdini-tool.py new file mode 100755 index 0000000..a2a0dec --- /dev/null +++ b/configs/scripts/houdini-tool.py @@ -0,0 +1,106 @@ +#! /usr/bin/env python3 + +# fmt:off +import sys +import os +from pathlib import Path +sys.path.append((Path(os.environ["EWCONFIG_ROOT"]) / "python_modules").as_posix()) +# fmt:on + +import argparse +import subprocess +import logging +from ewpipe.common.dirs import HOUDINI_PROJECTS_DIR +from ewpipe.houdini.editions import ( + get_binary_name_for_edition, + get_houdini_edition_args, + HOU_EDITIONS, +) +from ewpipe.houdini.installations import get_houdini_installation_path +from ewpipe.common.logging import configure_logging +from ewpipe.common.env import diff_from_current_env + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="houdini-tool", + description="Evan's tool for launching and managing Houdini", + ) + ap.add_argument( + "--type", + "-t", + help="Houdini type", + choices=HOU_EDITIONS, + default="apprentice", + ) + ap.add_argument( + "--project", + "-p", + help="Name of the project to open or create. May also be a direct path", + type=str, + required=True, + ) + ap.add_argument( + "--hou-version", + help="Houdini version to use. Defaults to latest", + type=str, + default=None, + ) + ap.add_argument( + "--no-project-env", help="Disables setting $HIP and $JOB", action="store_true" + ) + ap.add_argument("--verbose", "-v", help="Verbose output", action="store_true") + args = ap.parse_args() + + # Set up verbose logging if requested + configure_logging(verbose=args.verbose) + + # Get the houdini path + hou_path = get_houdini_installation_path(version=args.hou_version) + if not hou_path: + logger.error("Could not find Houdini installation") + return 1 + logger.info(f"Selected Houdini {hou_path.name[3:]} from {hou_path}") + + # Determine the project path + project_path = Path(args.project) + if not project_path.is_absolute(): + # This is a project name, not a path + project_path = HOUDINI_PROJECTS_DIR / project_path + logger.info(f"Opening project from: {project_path}") + + # If the directory does not exist, create + project_path.mkdir(parents=True, exist_ok=True) + + # If allowed, set up env vars + environment_vars = os.environ.copy() + environment_vars["HOUDINI_SCRIPT_DEBUG"] = "1" + environment_vars["HOUDINI_SPLASH_MESSAGE"] = "Loading with custom scripts" + environment_vars["HOUDINI_CONSOLE_PYTHON_PANEL_ERROR"] = "1" + if not args.no_project_env: + # environment_vars["HIP"] = str(project_path) + environment_vars["JOB"] = str(project_path) + environment_vars["HOUDINI_HIP_DEFAULT_NAME"] = f"{project_path.name}.hip" + + # Figure out what has changed in the environment and print the changes + env_changes = diff_from_current_env(environment_vars) + if env_changes: + logger.info("Environment changes:") + for key, value in env_changes.items(): + logger.info(f" ${key}: {value}") + + # Launch houdini + cmd = [ + str(hou_path / "bin" / get_binary_name_for_edition(args.type)), + "-foreground", + ] + get_houdini_edition_args(args.type) + logger.info(f"Running: {' '.join(cmd)}") + status = subprocess.run(cmd, env=environment_vars, cwd=project_path).returncode + return status + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/scripts/hython-latest b/configs/scripts/hython-latest new file mode 100755 index 0000000..205e7ca --- /dev/null +++ b/configs/scripts/hython-latest @@ -0,0 +1,9 @@ +#! /bin/bash +set -e + +# Find hython +HOUDINI_PATH=`python3 ~/.config/ewconfig/python_modules/ewpipe/houdini/installations.py` +HYTHON_PATH=$HOUDINI_PATH/bin/hython + +# Execute hython, passing through all arguments +$HYTHON_PATH $@ \ No newline at end of file diff --git a/configs/scripts/run-logid b/configs/scripts/run-logid old mode 100644 new mode 100755 diff --git a/configs/scripts/usdnc-to-usd.py b/configs/scripts/usdnc-to-usd.py new file mode 100755 index 0000000..9696096 --- /dev/null +++ b/configs/scripts/usdnc-to-usd.py @@ -0,0 +1,47 @@ +#! /usr/bin/env -S hython-latest -I +import argparse +import sys +from pxr import Usd +from pathlib import Path + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="usdnc-to-usd", description="Convert USDNC files to USD" + ) + ap.add_argument("input", help="Input file", type=Path) + ap.add_argument( + "--output", + "-o", + help="Output file. Defaults to the input file with a new extension.", + type=Path, + default=None, + ) + ap.add_argument( + "--format", + "-f", + help="Output format. Defaults to usda.", + type=str, + default="usda", + choices=["usda", "usdc"], + ) + args = ap.parse_args() + + # Read the input file + print(f"Opening stage from: {args.input}") + stage = Usd.Stage.Open(args.input.as_posix()) + + # Determine the output file + if not args.output: + args.output = args.input.with_suffix(f".{args.format}") + + # Write the output file + print(f"Writing stage to: {args.output}") + stage.Export(args.output.as_posix()) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/ssh/config b/configs/ssh/config index 85669c3..ed2ef05 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -74,6 +74,8 @@ Host sdf.org *.sdf.org # Guru Host *.gurustudio.com User "guru-domain\\epratten" +Host td-prod td-prod2 td-prod3 td-prod4 + User guru # Personal Infra Host oci-arm diff --git a/install.conf.yaml b/install.conf.yaml index 8cd76c1..21d61e1 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -55,6 +55,9 @@ ~/bin/run-logid: path: configs/scripts/run-logid mode: 755 + ~/bin/houdini-tool: configs/scripts/houdini-tool.py + ~/bin/hython-latest: configs/scripts/hython-latest + ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py # Systemd Services # ~/.config/systemd/user/logid.service: configs/systemd/user/logid.service @@ -71,6 +74,7 @@ ~/.config/termux/termux.properties: configs/termux/termux.properties ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf ~/.config/logid/logid.cfg: configs/logid/logid.cfg + ~/houdini19.5/scripts: configs/houdini19.5/scripts - shell: # Make sure we have our git modules @@ -78,9 +82,7 @@ # Install SSH config - [sh ./helpers/install-ssh-config.sh, Installing SSH config] # Ensure that all downloaded scripts are executable - - [chmod +x configs/scripts/catto, Making catto executable] - - [chmod +x configs/scripts/aspath, Making aspath executable] - - [chmod +x configs/scripts/fetch-steamdeck-screenshots, Making fetch-steamdeck-screenshots executable] + - [chmod +x configs/scripts/*, Making bin scripts executable] - [chmod +x configs/nautilus/scripts/*, Making nautilus scripts executable] # Configure GNOME - [sh ./helpers/configure-gnome.sh, Configuring GNOME] diff --git a/python_modules/ewpipe/common/dirs.py b/python_modules/ewpipe/common/dirs.py new file mode 100644 index 0000000..5a4546b --- /dev/null +++ b/python_modules/ewpipe/common/dirs.py @@ -0,0 +1,13 @@ +from pathlib import Path + +DCC_DATA_BASE_DIR = Path.home() / "Videos" / "DCC" +"""The base directory for storing data across DCCs""" + +HOUDINI_BASE_DIR = DCC_DATA_BASE_DIR / "Houdini" +"""The base directory for storing Houdini data""" + +HOUDINI_PROJECTS_DIR = HOUDINI_BASE_DIR / "Projects" +"""The base directory for storing Houdini projects""" + +BLENDER_BASE_DIR = DCC_DATA_BASE_DIR / "Blender" +"""The base directory for storing Blender data""" diff --git a/python_modules/ewpipe/common/env.py b/python_modules/ewpipe/common/env.py new file mode 100644 index 0000000..0d1368a --- /dev/null +++ b/python_modules/ewpipe/common/env.py @@ -0,0 +1,31 @@ +import os +from typing import Dict + + +def diff_environments(env_1: Dict[str, str], env_2: Dict[str, str]) -> Dict[str, str]: + """Diff two environments. + + Args: + env_1 (Dict[str,str]): First environment + env_2 (Dict[str,str]): Second environment + + Returns: + Dict[str,str]: Difference between the two environments + """ + return { + key: value + for key, value in env_1.items() + if key not in env_2 or env_2[key] != value + } + + +def diff_from_current_env(new_env: Dict[str, str]) -> Dict[str, str]: + """Diff the current environment from the given environment. + + Args: + new_env (Dict[str, str]): New environment + + Returns: + Dict[str, str]: Difference between the current environment and the given environment + """ + return diff_environments(os.environ, new_env) # type: ignore diff --git a/python_modules/ewpipe/common/logging.py b/python_modules/ewpipe/common/logging.py new file mode 100644 index 0000000..b45ad94 --- /dev/null +++ b/python_modules/ewpipe/common/logging.py @@ -0,0 +1,8 @@ +import logging + + +def configure_logging(verbose: bool = False): + logging.basicConfig( + level=logging.DEBUG if verbose else logging.INFO, + format="%(levelname)s:\t%(message)s", + ) diff --git a/python_modules/ewpipe/houdini/editions.py b/python_modules/ewpipe/houdini/editions.py new file mode 100644 index 0000000..af487c8 --- /dev/null +++ b/python_modules/ewpipe/houdini/editions.py @@ -0,0 +1,36 @@ +from typing import List + +HOU_EDITIONS = ["core", "fx", "indie", "apprentice"] +"""All possible Houdini editions.""" + + +def get_binary_name_for_edition(edition: str) -> str: + """Get the appropriate binary name for the given Houdini edition. + + Args: + edition (str): Hooudini edition + + Returns: + str: Binary name + """ + + if edition in ["core", "fx"]: + return f"houdini{edition}" + else: + return "houdini" + + +def get_houdini_edition_args(edition: str) -> List[str]: + """Get the appropriate arguments to launch a given Houdini edition. + + Args: + edition (str): Houdini edition + + Returns: + List[str]: Arguments + """ + + if edition in ["indie", "apprentice"]: + return [f"-{edition}"] + else: + return [] diff --git a/python_modules/ewpipe/houdini/installations.py b/python_modules/ewpipe/houdini/installations.py new file mode 100644 index 0000000..a6c009a --- /dev/null +++ b/python_modules/ewpipe/houdini/installations.py @@ -0,0 +1,129 @@ +import logging +import platform +import argparse +import sys +from pathlib import Path +from typing import Optional + +logger = logging.getLogger(__name__) + + +def get_default_houdini_installation_base_path() -> Path: + """Get the default Houdini installation base path. + + Returns: + Path: Default Houdini installation base path + """ + if platform.system() == "Linux": + return Path("/opt") + elif platform.system() == "Windows": + return Path("C:/Program Files/Side Effects Software") + else: + raise RuntimeError(f"Unsupported platform: {platform.system()}") + + +def find_latest_houdini_installation(base_path: Path) -> Optional[Path]: + """Find the latest Houdini installation in the given base path. + + Args: + base_path (Path): Base path to look for Houdini installations in. + + Returns: + Optional[Path]: Houdini installation path if found + """ + logger.debug(f"Looking for the latest Houdini installation in: {base_path}") + + # Look for possible houdini installations + if platform.system() == "Linux": + possible_installations = sorted(base_path.glob("hfs*")) + elif platform.system() == "Windows": + possible_installations = sorted(base_path.glob("Houdini *")) + else: + raise RuntimeError(f"Unsupported platform: {platform.system()}") + logger.debug( + f"Search found the following Houdini installations: {[str(i) for i in possible_installations]}" + ) + + # Remove `Houdini Server` if it exists + possible_installations = [ + installation + for installation in possible_installations + if "Server" not in installation.name + ] + + # If there are no installations, return None + if not possible_installations: + return None + + # Otherwise, return the latest installation + latest_installation = possible_installations[-1] + logger.debug(f"Latest Houdini installation: {latest_installation}") + return latest_installation + + +def get_houdini_installation_path( + version: Optional[str] = None, + base_path: Optional[Path] = None, + not_exists_ok: bool = False, +) -> Optional[Path]: + """Get the path to the Houdini installation for the given version. + + Args: + version (Optional[str], optional): Houdini version to target. Defaults to None. + not_exists_ok (bool, optional): If true, allows bad paths to be returned. Defaults to False. + + Raises: + RuntimeError: Thrown if the platform is not supported. + + Returns: + Optional[Path]: Path to the Houdini installation if found + """ + + logger.debug(f"Finding Houdini installation for version: {version}") + + # Get the default installation base path + if not base_path: + base_path = get_default_houdini_installation_base_path() + logger.debug(f"Searching for Houdini installations in: {base_path}") + + # If we don't have a version, find the latest installation + if not version: + logger.debug("No version specified, finding latest installation") + return find_latest_houdini_installation(base_path) + + # Otherwise, find the installation for the given version + if platform.system() == "Linux": + installation_path = base_path / f"hfs{version}" + elif platform.system() == "Windows": + installation_path = base_path / f"Houdini {version}" + else: + raise RuntimeError(f"Unsupported platform: {platform.system()}") + + # If the installation path does not exist, return None + if (not installation_path.exists()) and not not_exists_ok: + logger.debug(f"Installation path does not exist: {installation_path}") + return None + + # Otherwise, return the installation path + logger.debug(f"Found installation path: {installation_path}") + return installation_path + + +if __name__ == "__main__": + ap = argparse.ArgumentParser() + ap.add_argument("--version", "-v", help="Houdini version", type=str) + ap.add_argument("--base-path", "-b", help="Houdini base path", type=str) + ap.add_argument("--not-exists-ok", help="Allow bad paths", action="store_true") + args = ap.parse_args() + + result = get_houdini_installation_path( + version=args.version, + base_path=Path(args.base_path) if args.base_path else None, + not_exists_ok=args.not_exists_ok, + ) + if not result: + print("Could not find Houdini", file=sys.stderr) + sys.exit(1) + + print(result) + sys.exit(0) From d4d46af96ce426a77f8814d822f8f53e08a48bfb Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 5 Oct 2023 23:26:23 -0400 Subject: [PATCH 115/326] Add a script for converting usdnc to usd inside houdini --- .../scripts/post_frame_usdnc_to_usd.py | 17 +++++++++++++++++ configs/scripts/houdini-tool.py | 4 ++++ 2 files changed, 21 insertions(+) create mode 100644 configs/houdini19.5/scripts/post_frame_usdnc_to_usd.py diff --git a/configs/houdini19.5/scripts/post_frame_usdnc_to_usd.py b/configs/houdini19.5/scripts/post_frame_usdnc_to_usd.py new file mode 100644 index 0000000..22ed009 --- /dev/null +++ b/configs/houdini19.5/scripts/post_frame_usdnc_to_usd.py @@ -0,0 +1,17 @@ +from pxr import Usd +from pathlib import Path + +# Figure out what file just got exported +# NOTE: The filename the user enters is not the actual filename due to the NC suffix +output_file_field = Path(hou.pwd().parm("lopoutput").eval()) +rendered_file = output_file_field.with_suffix(".usdnc") +print(f"[USDNC To USD]: Converting {rendered_file} to USD") + +# Load the rendered stage +print("[USDNC To USD]: Loading stage") +stage = Usd.Stage.Open(str(rendered_file)) + +# Write it again with the appropriate extension +output_file = rendered_file.with_suffix(output_file_field.suffix) +print(f"[USDNC To USD]: Exporting to: {output_file}") +stage.Export(str(output_file)) diff --git a/configs/scripts/houdini-tool.py b/configs/scripts/houdini-tool.py index a2a0dec..4e45e38 100755 --- a/configs/scripts/houdini-tool.py +++ b/configs/scripts/houdini-tool.py @@ -97,6 +97,10 @@ def main() -> int: str(hou_path / "bin" / get_binary_name_for_edition(args.type)), "-foreground", ] + get_houdini_edition_args(args.type) + if (project_path / f"{project_path.name}.hip").exists(): + cmd.append(f"{project_path}/{project_path.name}.hip") + if (project_path / f"{project_path.name}.hipnc").exists(): + cmd.append(f"{project_path}/{project_path.name}.hipnc") logger.info(f"Running: {' '.join(cmd)}") status = subprocess.run(cmd, env=environment_vars, cwd=project_path).returncode return status From 4fda92008676936523b2c3f59254864771a875fe Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 7 Oct 2023 16:28:02 -0400 Subject: [PATCH 116/326] Added user tmpfile dir --- install.conf.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/install.conf.yaml b/install.conf.yaml index 21d61e1..405bb63 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -18,6 +18,7 @@ - ~/.config/logid - ~/.config/systemd/user - ~/.cargo + - ~/.config/user-tmpfiles.d # Program plugins - ~/.local/share/nautilus/scripts/ From acc96e3fade50fa7c404bf6ee47b1ea085685f16 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 9 Oct 2023 14:06:45 -0400 Subject: [PATCH 117/326] Adding Hou & RDP stuff --- .vscode/settings.json | 1 + configs/scripts/houdini-tool.py | 55 +++++++++++++------- helpers/generate-rdp-tls-certs.sh | 11 ++++ python_modules/ewpipe/common/utils/path.py | 11 ++++ python_modules/ewpipe/houdini/editions.py | 14 +++++ python_modules/ewpipe/houdini/environment.py | 37 +++++++++++++ 6 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 helpers/generate-rdp-tls-certs.sh create mode 100644 python_modules/ewpipe/common/utils/path.py create mode 100644 python_modules/ewpipe/houdini/environment.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 270f0cd..4877f66 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,4 +11,5 @@ "python.analysis.extraPaths": [ "./python_modules" ], + "python.formatting.provider": "black", } \ No newline at end of file diff --git a/configs/scripts/houdini-tool.py b/configs/scripts/houdini-tool.py index 4e45e38..436b9ed 100755 --- a/configs/scripts/houdini-tool.py +++ b/configs/scripts/houdini-tool.py @@ -11,14 +11,15 @@ import argparse import subprocess import logging from ewpipe.common.dirs import HOUDINI_PROJECTS_DIR +from ewpipe.common.utils.path import prepend_if_relative from ewpipe.houdini.editions import ( get_binary_name_for_edition, get_houdini_edition_args, HOU_EDITIONS, + noncomercialize_path, ) from ewpipe.houdini.installations import get_houdini_installation_path from ewpipe.common.logging import configure_logging -from ewpipe.common.env import diff_from_current_env logger = logging.getLogger(__name__) @@ -52,6 +53,10 @@ def main() -> int: ap.add_argument( "--no-project-env", help="Disables setting $HIP and $JOB", action="store_true" ) + ap.add_argument("--cpu", help="Use CPU compute for OpenCL", action="store_true") + ap.add_argument( + "--dump-core", help="Forces Houdini to dump its core", action="store_true" + ) ap.add_argument("--verbose", "-v", help="Verbose output", action="store_true") args = ap.parse_args() @@ -66,43 +71,53 @@ def main() -> int: logger.info(f"Selected Houdini {hou_path.name[3:]} from {hou_path}") # Determine the project path - project_path = Path(args.project) - if not project_path.is_absolute(): - # This is a project name, not a path - project_path = HOUDINI_PROJECTS_DIR / project_path + project_path = prepend_if_relative(HOUDINI_PROJECTS_DIR, Path(args.project)) + project_save_file = project_path / f"{project_path.name}.hip" logger.info(f"Opening project from: {project_path}") # If the directory does not exist, create project_path.mkdir(parents=True, exist_ok=True) # If allowed, set up env vars - environment_vars = os.environ.copy() - environment_vars["HOUDINI_SCRIPT_DEBUG"] = "1" - environment_vars["HOUDINI_SPLASH_MESSAGE"] = "Loading with custom scripts" - environment_vars["HOUDINI_CONSOLE_PYTHON_PANEL_ERROR"] = "1" + hou_env_settings = {} + hou_env_settings["HOUDINI_SCRIPT_DEBUG"] = "1" + hou_env_settings["HOUDINI_SPLASH_MESSAGE"] = "Loading with custom scripts" + hou_env_settings["HOUDINI_CONSOLE_PYTHON_PANEL_ERROR"] = "1" + hou_env_settings["HOUDINI_PDG_NODE_DEBUG"] = "3" + if args.cpu: + hou_env_settings["HOUDINI_OCL_DEVICETYPE"] = "CPU" + hou_env_settings["HOUDINI_USE_HFS_OCL"]="1" + if args.dump_core: + hou_env_settings["HOUDINI_COREDUMP"] = "1" if not args.no_project_env: # environment_vars["HIP"] = str(project_path) - environment_vars["JOB"] = str(project_path) - environment_vars["HOUDINI_HIP_DEFAULT_NAME"] = f"{project_path.name}.hip" + hou_env_settings["JOB"] = str(project_path) + hou_env_settings["HOUDINI_HIP_DEFAULT_NAME"] = project_save_file.name # Figure out what has changed in the environment and print the changes - env_changes = diff_from_current_env(environment_vars) - if env_changes: + if hou_env_settings: logger.info("Environment changes:") - for key, value in env_changes.items(): + for key, value in hou_env_settings.items(): logger.info(f" ${key}: {value}") + + # Combine the current environment with + cmd_env = dict(os.environ) + cmd_env.update(hou_env_settings) - # Launch houdini + # Build command to launch houdini cmd = [ str(hou_path / "bin" / get_binary_name_for_edition(args.type)), "-foreground", ] + get_houdini_edition_args(args.type) - if (project_path / f"{project_path.name}.hip").exists(): - cmd.append(f"{project_path}/{project_path.name}.hip") - if (project_path / f"{project_path.name}.hipnc").exists(): - cmd.append(f"{project_path}/{project_path.name}.hipnc") + + # If the expected project file exists already + # (aka, user already saved in a previous session), + # then conveniently open the project automatically + cmd.append(str(noncomercialize_path(project_save_file))) + + # Run houdini logger.info(f"Running: {' '.join(cmd)}") - status = subprocess.run(cmd, env=environment_vars, cwd=project_path).returncode + status = subprocess.run(cmd, env=cmd_env, cwd=project_path).returncode return status diff --git a/helpers/generate-rdp-tls-certs.sh b/helpers/generate-rdp-tls-certs.sh new file mode 100644 index 0000000..3a7a657 --- /dev/null +++ b/helpers/generate-rdp-tls-certs.sh @@ -0,0 +1,11 @@ +#! /bin/sh +set -e + +# Make the keys dir +KEYS_DIR=~/.config/gnome-remote-desktop/keys +mkdir -p $KEYS_DIR + +# Generate keys +openssl genrsa -out $KEYS_DIR/tls.key 4096 +openssl req -new -key $KEYS_DIR/tls.key -out $KEYS_DIR/tls.csr +openssl x509 -req -days 36500 -signkey $KEYS_DIR/tls.key -in $KEYS_DIR/tls.csr -out $KEYS_DIR/tls.crt diff --git a/python_modules/ewpipe/common/utils/path.py b/python_modules/ewpipe/common/utils/path.py new file mode 100644 index 0000000..0ba0a2a --- /dev/null +++ b/python_modules/ewpipe/common/utils/path.py @@ -0,0 +1,11 @@ +from pathlib import Path + + +def prepend_if_relative(prefix: Path, possibly_abs_path: Path) -> Path: + + # If absolute, no prepend needed + if possibly_abs_path.is_absolute(): + return possibly_abs_path + + # Otherwise prepend + return prefix / possibly_abs_path diff --git a/python_modules/ewpipe/houdini/editions.py b/python_modules/ewpipe/houdini/editions.py index af487c8..ee96dc0 100644 --- a/python_modules/ewpipe/houdini/editions.py +++ b/python_modules/ewpipe/houdini/editions.py @@ -1,4 +1,5 @@ from typing import List +from pathlib import Path HOU_EDITIONS = ["core", "fx", "indie", "apprentice"] """All possible Houdini editions.""" @@ -34,3 +35,16 @@ def get_houdini_edition_args(edition: str) -> List[str]: return [f"-{edition}"] else: return [] + + +def noncomercialize_path(input_path: Path) -> Path: + # Figure out the noncomercial version of the path + path_suffix = input_path.suffix + noncomercial_path = input_path.with_suffix(f".{path_suffix}nc") + + # If the NC version exists, use it + if noncomercial_path.exists(): + return noncomercial_path + + # All other cases, use the input directly + return input_path diff --git a/python_modules/ewpipe/houdini/environment.py b/python_modules/ewpipe/houdini/environment.py new file mode 100644 index 0000000..4bceff9 --- /dev/null +++ b/python_modules/ewpipe/houdini/environment.py @@ -0,0 +1,37 @@ +from dataclasses import dataclass, field, fields +from typing import Dict, Optional + + +@dataclass +class HoudiniEnvironment: + script_debug: bool = field(default=True, metadata={"key": "HOUDINI_SCRIPT_DEBUG"}) + """If set, errors will be printed when loading dialog scripts and scripted operators.""" + + show_py_panel_errors_in_console: bool = field( + default=True, metadata={"key": "HOUDINI_CONSOLE_PYTHON_PANEL_ERROR"} + ) + """Errors when starting python panels will also be sent to the console, instead of just displaying them within the panel.""" + + pdg_node_debug_level: int = field( + default=3, metadata={"key": "HOUDINI_PDG_NODE_DEBUG"} + ) + """Determines if PDG should print out node status information during the cook. + + 1: Enable a status print out message each time a node finishes cooking + 2: 1 + node error messages + 3: Print node generation/cook status, errors and node warnings + 4: 3 + print a message for each node callback invocation + """ + + splash_message: Optional[str] = field( + default=None, metadata={"key": "HOUDINI_SPLASH_MESSAGE"} + ) + """Message shown on the splash screen""" + + def to_dict(self) -> Dict[str, str]: + output: Dict[str, str] = {} + for obj_field in fields(self): + field_value = self.__dict__[obj_field.name] + if field_value: + output[obj_field.metadata["key"]] = str() + return output From 473d712dcb25d38db71234a3658a90801b939547 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 9 Oct 2023 14:32:47 -0400 Subject: [PATCH 118/326] Update --- helpers/generate-rdp-tls-certs.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helpers/generate-rdp-tls-certs.sh b/helpers/generate-rdp-tls-certs.sh index 3a7a657..594e93a 100644 --- a/helpers/generate-rdp-tls-certs.sh +++ b/helpers/generate-rdp-tls-certs.sh @@ -1,4 +1,4 @@ -#! /bin/sh +#! /bin/bash set -e # Make the keys dir @@ -6,6 +6,6 @@ KEYS_DIR=~/.config/gnome-remote-desktop/keys mkdir -p $KEYS_DIR # Generate keys -openssl genrsa -out $KEYS_DIR/tls.key 4096 +openssl genrsa -out $KEYS_DIR/tls.key 4096 openssl req -new -key $KEYS_DIR/tls.key -out $KEYS_DIR/tls.csr openssl x509 -req -days 36500 -signkey $KEYS_DIR/tls.key -in $KEYS_DIR/tls.csr -out $KEYS_DIR/tls.crt From 7c77672226ad92ffd9e6450809554983a696f757 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 9 Oct 2023 14:34:11 -0400 Subject: [PATCH 119/326] Dont load proj files if they dont exist --- configs/scripts/houdini-tool.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configs/scripts/houdini-tool.py b/configs/scripts/houdini-tool.py index 436b9ed..292ea76 100755 --- a/configs/scripts/houdini-tool.py +++ b/configs/scripts/houdini-tool.py @@ -113,7 +113,9 @@ def main() -> int: # If the expected project file exists already # (aka, user already saved in a previous session), # then conveniently open the project automatically - cmd.append(str(noncomercialize_path(project_save_file))) + proj_file = noncomercialize_path(project_save_file) + if proj_file.exists(): + cmd.append(str(proj_file)) # Run houdini logger.info(f"Running: {' '.join(cmd)}") From 78be1a31eb63229f59f8ee64e767db501112d950 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Oct 2023 11:04:59 -0400 Subject: [PATCH 120/326] cleanup --- configs/nautilus/scripts/USDView | 5 +++ helpers/generate-rdp-tls-certs.sh | 11 ------ install.conf.yaml | 40 ++++++++++++--------- solutions/configure-gnome-remote-desktop.sh | 23 ++++++++++++ 4 files changed, 52 insertions(+), 27 deletions(-) create mode 100755 configs/nautilus/scripts/USDView delete mode 100644 helpers/generate-rdp-tls-certs.sh create mode 100755 solutions/configure-gnome-remote-desktop.sh diff --git a/configs/nautilus/scripts/USDView b/configs/nautilus/scripts/USDView new file mode 100755 index 0000000..67120d5 --- /dev/null +++ b/configs/nautilus/scripts/USDView @@ -0,0 +1,5 @@ +#! /bin/sh +set -e + +usdview $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS + diff --git a/helpers/generate-rdp-tls-certs.sh b/helpers/generate-rdp-tls-certs.sh deleted file mode 100644 index 594e93a..0000000 --- a/helpers/generate-rdp-tls-certs.sh +++ /dev/null @@ -1,11 +0,0 @@ -#! /bin/bash -set -e - -# Make the keys dir -KEYS_DIR=~/.config/gnome-remote-desktop/keys -mkdir -p $KEYS_DIR - -# Generate keys -openssl genrsa -out $KEYS_DIR/tls.key 4096 -openssl req -new -key $KEYS_DIR/tls.key -out $KEYS_DIR/tls.csr -openssl x509 -req -days 36500 -signkey $KEYS_DIR/tls.key -in $KEYS_DIR/tls.csr -out $KEYS_DIR/tls.crt diff --git a/install.conf.yaml b/install.conf.yaml index 405bb63..3b38e83 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -2,7 +2,7 @@ link: relink: true -- clean: ['~'] +- clean: ["~"] - create: # Common organizational dirs @@ -21,14 +21,14 @@ - ~/.config/user-tmpfiles.d # Program plugins - ~/.local/share/nautilus/scripts/ - + - link: # Git ~/.gitconfig: configs/git/.gitconfig ~/.ssh/allowed_signers: configs/ssh/allowed_signers # Shell - ~/.zshrc: + ~/.zshrc: path: configs/zsh/.zshrc force: true @@ -53,6 +53,9 @@ ~/.local/share/nautilus/scripts/Open in Video Trimmer: path: configs/nautilus/scripts/Open in Video Trimmer mode: 755 + ~/.local/share/nautilus/scripts/USDView: + path: configs/nautilus/scripts/USDView + mode: 755 ~/bin/run-logid: path: configs/scripts/run-logid mode: 755 @@ -76,18 +79,23 @@ ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf ~/.config/logid/logid.cfg: configs/logid/logid.cfg ~/houdini19.5/scripts: configs/houdini19.5/scripts + ~/sln: solutions - shell: - # Make sure we have our git modules - - [git submodule update --init --recursive, Installing submodules] - # Install SSH config - - [sh ./helpers/install-ssh-config.sh, Installing SSH config] - # Ensure that all downloaded scripts are executable - - [chmod +x configs/scripts/*, Making bin scripts executable] - - [chmod +x configs/nautilus/scripts/*, Making nautilus scripts executable] - # Configure GNOME - - [sh ./helpers/configure-gnome.sh, Configuring GNOME] - # Configure Termux if on Android - - [termux-reload-settings || true, Trying to reload Termux] - # Configure Git - - [bash ./helpers/git-config-features.sh, Setting up optional git-config features] + # Make sure we have our git modules + - [git submodule update --init --recursive, Installing submodules] + # Install SSH config + - [sh ./helpers/install-ssh-config.sh, Installing SSH config] + # Ensure that all downloaded scripts are executable + - [chmod +x configs/scripts/*, Making bin scripts executable] + - [chmod +x configs/nautilus/scripts/*, Making nautilus scripts executable] + - [chmod +x solutions/*, Making solution scripts executable] + # Configure GNOME + - [sh ./helpers/configure-gnome.sh, Configuring GNOME] + # Configure Termux if on Android + - [termux-reload-settings || true, Trying to reload Termux] + # Configure Git + - [ + bash ./helpers/git-config-features.sh, + Setting up optional git-config features, + ] diff --git a/solutions/configure-gnome-remote-desktop.sh b/solutions/configure-gnome-remote-desktop.sh new file mode 100755 index 0000000..cd39885 --- /dev/null +++ b/solutions/configure-gnome-remote-desktop.sh @@ -0,0 +1,23 @@ +#! /bin/bash +# This script will do the work needed to configure Gnome Remote Desktop headlessly. +# Useful if you need RDP access to a remote machine and forgot to configure it before-hand +set -e + +# Make the keys dir +KEYS_DIR=~/.config/gnome-remote-desktop/keys +mkdir -p $KEYS_DIR + +# Generate keys +openssl genrsa -out $KEYS_DIR/tls.key 4096 +openssl req -new -key $KEYS_DIR/tls.key -out $KEYS_DIR/tls.csr +openssl x509 -req -days 36500 -signkey $KEYS_DIR/tls.key -in $KEYS_DIR/tls.csr -out $KEYS_DIR/tls.crt + +# Set the certificates +grdctl rdp set-tls-cert $KEYS_DIR/tls.crt +grdctl rdp set-tls-key $KEYS_DIR/tls.key +grdctl rdp disable-view-only + +# Inform of that to run next +echo "To finish GRD RDP setup, run:\ +\n\tgrdctl rdp set-credentials \ +\n\tgrdctl rdp enable" \ No newline at end of file From 4d837d7a1d62d723f0b60e5d43bc1a38d6e711bd Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Oct 2023 11:08:16 -0400 Subject: [PATCH 121/326] some info --- README.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5068b45..7856aaf 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,20 @@ # *ew*pratten's *config* files +This repository stores *most* of my common config files. It is designed to be deployable to pretty much any UNIX-like system. Assuming ideal conditions, any machine is one `./install` away from behaving like my personal workstation. + +## Setup + +The scripts in this repository have the following dependencies: + +- Git +- ZSH (optional, recommended) +- Neovim (optional, recommended) + +Install and link everything with: + ```sh mkdir -p ~/.config && cd ~/.config git clone https://github.com/ewpratten/ewconfig cd ewconfig ./install -``` - -## Dependencies - -- Git -- ZSH (optional, recommended) -- Neovim (optional, recommended) +``` \ No newline at end of file From 953268f931deefa80206194626f1d58838469056 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Oct 2023 11:45:01 -0400 Subject: [PATCH 122/326] Add script to autoconnect to guru vpn --- .vscode/tasks.json | 13 ++++ configs/scripts/guru-vpn.py | 114 ++++++++++++++++++++++++++++++++++++ install.conf.yaml | 1 + 3 files changed, 128 insertions(+) create mode 100644 .vscode/tasks.json create mode 100755 configs/scripts/guru-vpn.py diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..54e38d5 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,13 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Run install script", + "type": "shell", + "command": "./install", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/configs/scripts/guru-vpn.py b/configs/scripts/guru-vpn.py new file mode 100755 index 0000000..ef40815 --- /dev/null +++ b/configs/scripts/guru-vpn.py @@ -0,0 +1,114 @@ +#! /usr/bin/env python3 +import argparse +import sys +import subprocess +from typing import Optional + + +def has_ykman() -> bool: + try: + subprocess.run(["ykman", "--version"], check=True, stdout=subprocess.DEVNULL) + return True + except subprocess.CalledProcessError: + return False + + +def has_yk_plugged_in() -> bool: + devices = subprocess.run(["ykman", "list"], check=True, stdout=subprocess.PIPE) + devices = devices.stdout.decode("utf-8").split("\n") + return len(devices) > 1 + + +def is_interface_up(interface: str) -> bool: + try: + subprocess.run( + ["ip", "link", "show", interface], check=True, stdout=subprocess.DEVNULL + ) + return True + except subprocess.CalledProcessError: + return False + + +def get_oath_code(service: str) -> Optional[int]: + response = subprocess.run( + ["ykman", "oath", "accounts", "code", "Guru"], + check=True, + stdout=subprocess.PIPE, + ) + output = response.stdout.decode("utf-8") + if not output: + return None + return int(output.split("\n")[0].split(" ")[-1]) + + +def get_password(label: str, ns: str, key: str) -> str: + # Try to find it + try: + result = subprocess.run( + ["secret-tool", "lookup", ns, key], check=True, stdout=subprocess.PIPE + ) + return result.stdout.decode("utf-8") + except subprocess.CalledProcessError: + # If we are here, it doesn't exist + print(f"Enter your {label}") + subprocess.run(["secret-tool", "store", "--label", label, ns, key], check=True) + return get_password(label, ns, key) + + +def handle_connect(args: argparse.Namespace) -> int: + # If we are connected to AS54041, we need to briefly kill the connection + if is_interface_up("vpn"): + print("Bringing down AS54041 VPN") + subprocess.run(["sudo", "wg-quick", "down", "vpn"], check=True) + + # Get the base password + base_password = get_password("Guru VPN Password", "guru-vpn", "base-password") + + # Fetch the credentials from the Yubikey + oath_code = get_oath_code("Guru") + print(f"Using OATH code: {oath_code}") + + # Construct the one-time password + password = f"{base_password}{oath_code}" + + # Connect via nmcli + print("Bringing up Guru VPN") + subprocess.run( + [ + "nmcli", + "connection", + "modify", + "Guru VPN", + "vpn.secrets", + f"password={password}", + ], + check=True, + ) + subprocess.run(["nmcli", "connection", "up", "Guru VPN"], check=True) + + # Bring AS54041 back up + print("Bringing up AS54041 VPN") + subprocess.run(["sudo", "wg-quick", "up", "vpn"], check=True) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="guru-vpn", description="Utility for connecting to the Guru VPN" + ) + ap.add_argument("operation", choices=["connect"], help="Operation to perform") + args = ap.parse_args() + + # Ensure we can actually get credentials from the Yubikey + if not has_ykman(): + print("Could not execute `ykman`. Is it installed?", file=sys.stderr) + if not has_yk_plugged_in(): + print("Could not find YubiKey. Is it plugged in?", file=sys.stderr) + + # Handle subcommands + cmd_fns = {"connect": handle_connect} + return cmd_fns[args.operation](args) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/install.conf.yaml b/install.conf.yaml index 3b38e83..fb3448c 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -62,6 +62,7 @@ ~/bin/houdini-tool: configs/scripts/houdini-tool.py ~/bin/hython-latest: configs/scripts/hython-latest ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py + ~/bin/guru-vpn: configs/scripts/guru-vpn.py # Systemd Services # ~/.config/systemd/user/logid.service: configs/systemd/user/logid.service From 7c0c3b4f1729f54651c85e0d83c8200ffa02628d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Oct 2023 15:48:07 -0400 Subject: [PATCH 123/326] Load USDA syntax defs --- .gitmodules | 3 +++ configs/nvim/third_party/usda-syntax | 1 + 2 files changed, 4 insertions(+) create mode 160000 configs/nvim/third_party/usda-syntax diff --git a/.gitmodules b/.gitmodules index 9a866fe..2342512 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ path = configs/nvim/pack/airblade/start/vim-gitgutter url = https://github.com/airblade/vim-gitgutter.git ignore = dirty +[submodule "configs/nvim/third_party/usda-syntax"] + path = configs/nvim/third_party/usda-syntax + url = https://github.com/superfunc/usda-syntax diff --git a/configs/nvim/third_party/usda-syntax b/configs/nvim/third_party/usda-syntax new file mode 160000 index 0000000..deb110f --- /dev/null +++ b/configs/nvim/third_party/usda-syntax @@ -0,0 +1 @@ +Subproject commit deb110f0224235fcc19325b20885e566f911f84b From 74b7de77c578bf7cc465fcd70f6f8697a0887ff6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Oct 2023 15:48:16 -0400 Subject: [PATCH 124/326] Configure nvim to read USDA --- .../scripts/{USDView => Open with USDView} | 0 configs/nvim/init.vim | 7 ++++ install.conf.yaml | 35 +++++++------------ 3 files changed, 20 insertions(+), 22 deletions(-) rename configs/nautilus/scripts/{USDView => Open with USDView} (100%) diff --git a/configs/nautilus/scripts/USDView b/configs/nautilus/scripts/Open with USDView similarity index 100% rename from configs/nautilus/scripts/USDView rename to configs/nautilus/scripts/Open with USDView diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 0768444..bd475f0 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -55,6 +55,13 @@ set nocompatible filetype plugin on syntax on +" Custom syntax highlighting +if !exists('g:vscode') + au BufRead,BufNewFile *.usd set filetype=usda + au BufRead,BufNewFile *.usda set filetype=usda + autocmd FileType usda source ~/.config/nvim/third_party/usda-syntax/vim/usda.vim +endif + " Hide the intro message set shortmess+=I diff --git a/install.conf.yaml b/install.conf.yaml index fb3448c..56555c0 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -35,37 +35,28 @@ # Vim ~/.config/nvim/init.vim: configs/nvim/init.vim ~/.config/nvim/pack: configs/nvim/pack - # ~/.config/nvim/spell: configs/nvim/en.utf-8.add + ~/.config/nvim/third_party: configs/nvim/third_party # Scripts - ~/bin/catto: - path: configs/scripts/catto - mode: 755 - ~/bin/aspath: - path: configs/scripts/aspath - mode: 755 - ~/bin/fetch-steamdeck-screenshots: - path: configs/scripts/fetch-steamdeck-screenshots - mode: 755 + ~/bin/catto: configs/scripts/catto + ~/bin/aspath: configs/scripts/aspath + ~/bin/fetch-steamdeck-screenshots: configs/scripts/fetch-steamdeck-screenshots + ~/bin/run-logid: configs/scripts/run-logid + ~/bin/houdini-tool: configs/scripts/houdini-tool.py + ~/bin/hython-latest: configs/scripts/hython-latest + ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py + ~/bin/guru-vpn: configs/scripts/guru-vpn.py + + # Nautilus right-click scripts ~/.local/share/nautilus/scripts/Copy to web: path: configs/nautilus/scripts/Copy to web mode: 755 ~/.local/share/nautilus/scripts/Open in Video Trimmer: path: configs/nautilus/scripts/Open in Video Trimmer mode: 755 - ~/.local/share/nautilus/scripts/USDView: - path: configs/nautilus/scripts/USDView + ~/.local/share/nautilus/scripts/Open with USDView: + path: configs/nautilus/scripts/Open with USDView mode: 755 - ~/bin/run-logid: - path: configs/scripts/run-logid - mode: 755 - ~/bin/houdini-tool: configs/scripts/houdini-tool.py - ~/bin/hython-latest: configs/scripts/hython-latest - ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py - ~/bin/guru-vpn: configs/scripts/guru-vpn.py - - # Systemd Services - # ~/.config/systemd/user/logid.service: configs/systemd/user/logid.service # XDG Autostart ~/.config/autostart/gnome-keyring-ssh.desktop: configs/autostart/gnome-keyring-ssh.desktop From 24353dd425261566bddbc86660f45f3d7bd3ca90 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Oct 2023 15:48:33 -0400 Subject: [PATCH 125/326] no spell in USDA files --- configs/nvim/init.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index bd475f0..07ab87c 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -80,6 +80,7 @@ if !exists('g:vscode') " Disable spellcheck for some file formats autocmd FileType man setlocal nospell autocmd FileType diff setlocal nospell + autocmd FileType usda setlocal nospell endif " Configure Diff rendering From 7dddef47e8c14576a70311f9e2de7277b78fe57b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 11 Oct 2023 23:39:16 -0400 Subject: [PATCH 126/326] Add sub-project support --- configs/scripts/houdini-tool.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/configs/scripts/houdini-tool.py b/configs/scripts/houdini-tool.py index 292ea76..e0d61a1 100755 --- a/configs/scripts/houdini-tool.py +++ b/configs/scripts/houdini-tool.py @@ -44,6 +44,13 @@ def main() -> int: type=str, required=True, ) + ap.add_argument( + "--sub-project", + "--sp", + help="Name of the sub-project to open", + type=str, + default=None, + ) ap.add_argument( "--hou-version", help="Houdini version to use. Defaults to latest", @@ -72,11 +79,14 @@ def main() -> int: # Determine the project path project_path = prepend_if_relative(HOUDINI_PROJECTS_DIR, Path(args.project)) - project_save_file = project_path / f"{project_path.name}.hip" + project_save_file = project_path / ( + f"{args.sub_project}.hip" if args.sub_project else f"{project_path.name}.hip" + ) logger.info(f"Opening project from: {project_path}") # If the directory does not exist, create project_path.mkdir(parents=True, exist_ok=True) + (project_path / "render").mkdir(parents=True, exist_ok=True) # If allowed, set up env vars hou_env_settings = {} @@ -86,7 +96,7 @@ def main() -> int: hou_env_settings["HOUDINI_PDG_NODE_DEBUG"] = "3" if args.cpu: hou_env_settings["HOUDINI_OCL_DEVICETYPE"] = "CPU" - hou_env_settings["HOUDINI_USE_HFS_OCL"]="1" + hou_env_settings["HOUDINI_USE_HFS_OCL"] = "1" if args.dump_core: hou_env_settings["HOUDINI_COREDUMP"] = "1" if not args.no_project_env: @@ -99,8 +109,8 @@ def main() -> int: logger.info("Environment changes:") for key, value in hou_env_settings.items(): logger.info(f" ${key}: {value}") - - # Combine the current environment with + + # Combine the current environment with cmd_env = dict(os.environ) cmd_env.update(hou_env_settings) From 08464fe6123076838b9bf7b32a75d23d30a94ab0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 09:43:02 -0400 Subject: [PATCH 127/326] tweak vpn tool --- configs/scripts/guru-vpn.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/configs/scripts/guru-vpn.py b/configs/scripts/guru-vpn.py index ef40815..b6ede10 100755 --- a/configs/scripts/guru-vpn.py +++ b/configs/scripts/guru-vpn.py @@ -56,6 +56,10 @@ def get_password(label: str, ns: str, key: str) -> str: def handle_connect(args: argparse.Namespace) -> int: + if not has_yk_plugged_in(): + print("Could not find YubiKey. Is it plugged in?", file=sys.stderr) + return 1 + # If we are connected to AS54041, we need to briefly kill the connection if is_interface_up("vpn"): print("Bringing down AS54041 VPN") @@ -91,22 +95,30 @@ def handle_connect(args: argparse.Namespace) -> int: subprocess.run(["sudo", "wg-quick", "up", "vpn"], check=True) +def handle_disconnect(args: argparse.Namespace) -> int: + # Disconnect from Guru VPN + print("Bringing down Guru VPN") + result = subprocess.run(["nmcli", "connection", "down", "Guru VPN"]) + return result.returncode + + def main() -> int: # Handle program arguments ap = argparse.ArgumentParser( prog="guru-vpn", description="Utility for connecting to the Guru VPN" ) - ap.add_argument("operation", choices=["connect"], help="Operation to perform") + ap.add_argument( + "operation", choices=["connect", "disconnect"], help="Operation to perform" + ) args = ap.parse_args() # Ensure we can actually get credentials from the Yubikey if not has_ykman(): - print("Could not execute `ykman`. Is it installed?", file=sys.stderr) - if not has_yk_plugged_in(): - print("Could not find YubiKey. Is it plugged in?", file=sys.stderr) + print("Could not execute `ykman`. Is it installed?", file=sys.stderr); + return 1 # Handle subcommands - cmd_fns = {"connect": handle_connect} + cmd_fns = {"connect": handle_connect, "disconnect": handle_disconnect} return cmd_fns[args.operation](args) From c12fdb90dbb53b680202dafd720ddbad31b46a8b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 12:39:31 -0400 Subject: [PATCH 128/326] Configure git email --- configs/git/.gitconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index ce86ee2..a2f753e 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -2,7 +2,7 @@ path = ~/.config/git/features/enable-signing.gitconfig [user] - email = ewpratten@gmail.com + email = evan@ewpratten.com name = Evan Pratten signingkey = ~/.ssh/id_ed25519_sk_rk_yk20572395 @@ -36,3 +36,8 @@ helper = helper = !/usr/bin/gh auth git-credential +[sendemail] + smtpserver = smtp.migadu.com + smtpuser = evan@ewpratten.com + smtpencryption = tls + smtpserverport = 587 From 83b51cd03f57c152ff6adf2444ba8d07fbbea549 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 14:58:58 -0400 Subject: [PATCH 129/326] Enable modeline --- configs/nvim/init.vim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 07ab87c..bdf8063 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -2,6 +2,9 @@ " Syntax highlighting syntax on +" Enable modeline +set modeline + " Enable mouse usage set mouse=a From eec5708d33f0d48f1dc935cd3e4fa0f931356302 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 16:27:47 -0400 Subject: [PATCH 130/326] Wg macros --- configs/ssh/config | 5 +++-- configs/zsh/macros.sh | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/configs/ssh/config b/configs/ssh/config index ed2ef05..b005789 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -1,8 +1,9 @@ +# vim: nospell # Global Rules Host * !*.github.com !github.com IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 IdentityFile %d/.ssh/id_ed25519 - IdentityFile %d/.ssh/id_rsa + # IdentityFile %d/.ssh/id_rsa VisualHostKey yes # Github SSH adapter for restricted networks @@ -12,7 +13,7 @@ Host github.com gist.github.com # This solves a VSCode bug IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 - IdentityFile %d/.ssh/id_rsa + # IdentityFile %d/.ssh/id_rsa # Home network Host unifi diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index d523e58..654924d 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -13,6 +13,7 @@ alias lsgrep="ls | grep" alias sheridan-rdp='firefox --new-window "ext+container:name=College&url=https://client.wvd.microsoft.com/arm/webclient/index.html"' alias git-diff-nvim="git diff | nvim -R -d -c 'set filetype=diff' -" alias yk-totp="ykman oath accounts code" +alias flush-dns-cache="sudo systemd-resolve --flush-caches" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" @@ -125,7 +126,8 @@ wg-restart() { if [ $# != 1 ]; then echo "Usage: wg-restart " else - wg-quick down $1 && wg-quick up $1 + wg-quick down $1 || true; + wg-quick up $1 fi } @@ -137,3 +139,21 @@ wg-reload() { wg syncconf $1 <(wg-quick strip $1) fi } + +# Edit a wireguard config file +wg-edit() { + if [ $# != 1 ]; then + echo "Usage: wg-edit " + else + sudo nvim /etc/wireguard/$1.conf + fi +} + +# Print a wireguard config file +wg-cat() { + if [ $# != 1 ]; then + echo "Usage: wg-cat " + else + sudo cat /etc/wireguard/$1.conf + fi +} From ec922af58bc038ff069f4e5ced0d3ca90afb1fe3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 16:28:56 -0400 Subject: [PATCH 131/326] ewc pull --- configs/zsh/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 654924d..82b8706 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -14,6 +14,7 @@ alias sheridan-rdp='firefox --new-window "ext+container:name=College&url=https:/ alias git-diff-nvim="git diff | nvim -R -d -c 'set filetype=diff' -" alias yk-totp="ykman oath accounts code" alias flush-dns-cache="sudo systemd-resolve --flush-caches" +alias ewconfig-pull="cd ~/.config/ewconfig; git pull" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From 4c6f7419aab95468d9de2c9a287e3edadf172a03 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 18:05:06 -0400 Subject: [PATCH 132/326] Create dirs --- install.conf.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/install.conf.yaml b/install.conf.yaml index 56555c0..018b740 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -17,10 +17,12 @@ - ~/.config/termux - ~/.config/logid - ~/.config/systemd/user + - ~/.config/autostart - ~/.cargo - ~/.config/user-tmpfiles.d # Program plugins - ~/.local/share/nautilus/scripts/ + - ~/houdini19.5 - link: # Git From 84566fc9ff60914c867f7369415266e8cd93d3b8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 19:13:27 -0400 Subject: [PATCH 133/326] wip wg-handshakes --- configs/scripts/wg-handshakes.py | 111 +++++++++++++++++++++++++++++++ install.conf.yaml | 1 + 2 files changed, 112 insertions(+) create mode 100755 configs/scripts/wg-handshakes.py diff --git a/configs/scripts/wg-handshakes.py b/configs/scripts/wg-handshakes.py new file mode 100755 index 0000000..601ff0c --- /dev/null +++ b/configs/scripts/wg-handshakes.py @@ -0,0 +1,111 @@ +#! /usr/bin/env python3 +import argparse +import sys +import subprocess +from datetime import datetime +from typing import List, Optional + +try: + import timeago +except ImportError: + print( + "Required dependency missing. Install by running: pip3 install timeago", + file=sys.stderr, + ) + sys.exit(1) + + +def get_name_for_client( + pubkey: str, endpoint: str, allowed_ips: List[str], dns_server: Optional[str] = None +) -> str: + # Build the dig command prefix + dig_cmd_pfx = ["dig"] + if dns_server: + dig_cmd_pfx.append(f"@{dns_server}") + + # Search through the allowed ips for addresses with reverse dns + for ip in allowed_ips: + ip = ip.split("/")[0] + try: + name = subprocess.check_output(dig_cmd_pfx + ["-x", ip, "+short"]).decode( + "utf-8" + ) + name = name.strip() + if name != "": + return name[:-1] + except subprocess.CalledProcessError: + pass + + # Check the endpoint for reverse dns + try: + name = subprocess.check_output(dig_cmd_pfx + ["-x", endpoint, "+short"]).decode( + "utf-8" + ) + name = name.strip() + if name != "": + return name[:-1] + except subprocess.CalledProcessError: + pass + + # If all else fails, return the first 8 characters of the public key followed by ... + return pubkey[:8] + "..." + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="wg-handshakes", description="List the recency of WireGuard handshakes" + ) + ap.add_argument( + "--interface", "-i", help="The WireGuard interface to use", default="all" + ) + ap.add_argument( + "--no-sudo", help="Do not use sudo when running commands", action="store_true" + ) + ap.add_argument( + "--dns-server", "-d", help="Override the DNS server to use for RDNS lookups" + ) + args = ap.parse_args() + + # Get the output of wg show + cmd = ["wg", "show", args.interface, "dump"] + if not args.no_sudo: + cmd.insert(0, "sudo") + output = subprocess.check_output(cmd).decode("utf-8") + + # For every line (client) except the first (this device) + lines = output.split("\n")[1:] + for line in lines: + # values are in TSV + values = line.split("\t") + + # If the interface is `all`, ignore the first value + if args.interface == "all": + values = values[1:] + + # If the line is empty, skip it + if len(values) == 0: + continue + + # Get the client's public key + pubkey = values[0] + + # Read the IPs of the client to guess its name + allowed_ips = values[3].split(",") + endpoint = values[2].split(":")[0] + + # Get the name of the client + name = get_name_for_client(pubkey, endpoint, allowed_ips, args.dns_server) + + # Get the time of the last handshake + last_handshake = datetime.fromtimestamp(int(values[4])) + time_ago = timeago.format(last_handshake, datetime.now()) + + # Print the client's name and the time of the last handshake + print(f"{name}: {time_ago}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/install.conf.yaml b/install.conf.yaml index 018b740..0f298ac 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -48,6 +48,7 @@ ~/bin/hython-latest: configs/scripts/hython-latest ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py ~/bin/guru-vpn: configs/scripts/guru-vpn.py + ~/bin/wg-handshakes: configs/scripts/wg-handshakes.py # Nautilus right-click scripts ~/.local/share/nautilus/scripts/Copy to web: From bcdc5a923812dcd3511f0e676b55cd62a0ad9c79 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 19:14:43 -0400 Subject: [PATCH 134/326] Specify Never --- configs/scripts/wg-handshakes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/scripts/wg-handshakes.py b/configs/scripts/wg-handshakes.py index 601ff0c..1dab4cd 100755 --- a/configs/scripts/wg-handshakes.py +++ b/configs/scripts/wg-handshakes.py @@ -99,7 +99,7 @@ def main() -> int: # Get the time of the last handshake last_handshake = datetime.fromtimestamp(int(values[4])) - time_ago = timeago.format(last_handshake, datetime.now()) + time_ago = timeago.format(last_handshake, datetime.now()) if values[4] != "0" else "Never" # Print the client's name and the time of the last handshake print(f"{name}: {time_ago}") From f5553fc8fb738c0b71600651d8d0b84bfaf14296 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 12 Oct 2023 19:16:17 -0400 Subject: [PATCH 135/326] sort --- configs/scripts/wg-handshakes.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/configs/scripts/wg-handshakes.py b/configs/scripts/wg-handshakes.py index 1dab4cd..dc8a574 100755 --- a/configs/scripts/wg-handshakes.py +++ b/configs/scripts/wg-handshakes.py @@ -75,6 +75,7 @@ def main() -> int: # For every line (client) except the first (this device) lines = output.split("\n")[1:] + outputs = [] for line in lines: # values are in TSV values = line.split("\t") @@ -99,10 +100,20 @@ def main() -> int: # Get the time of the last handshake last_handshake = datetime.fromtimestamp(int(values[4])) - time_ago = timeago.format(last_handshake, datetime.now()) if values[4] != "0" else "Never" + time_ago = ( + timeago.format(last_handshake, datetime.now()) + if values[4] != "0" + else "Never" + ) - # Print the client's name and the time of the last handshake - print(f"{name}: {time_ago}") + outputs.append((name, last_handshake, time_ago)) + + # Sort the outputs by time + outputs.sort(key=lambda x: x[1], reverse=True) + + # Print the outputs + for output in outputs: + print(f"{output[0]}: {output[2]}") return 0 From 47a22743750a3791aaaf29560a690aa822ce651b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 09:08:35 -0400 Subject: [PATCH 136/326] Add proc-grep --- configs/zsh/macros.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 82b8706..41869fc 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -158,3 +158,12 @@ wg-cat() { sudo cat /etc/wireguard/$1.conf fi } + +# Search for a process +proc-grep() { + if [ $# != 1 ]; then + echo "Usage: proc-grep " + else + ps aux | { head -1; grep $1 } + fi +} From a6631cda832253d6479a02b2ef722f5c8760674a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:27:47 -0400 Subject: [PATCH 137/326] genzone --- configs/scripts/wg-genzone.py | 142 ++++++++++++++++++++++++++++++++++ install.conf.yaml | 1 + 2 files changed, 143 insertions(+) create mode 100755 configs/scripts/wg-genzone.py diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py new file mode 100755 index 0000000..b67cd7b --- /dev/null +++ b/configs/scripts/wg-genzone.py @@ -0,0 +1,142 @@ +#! /usr/bin/env python3 +import argparse +import sys +import subprocess +import ipaddress +import json +from typing import Optional, List, Tuple, Union +from dataclasses import dataclass + + +@dataclass +class PeerMetadata: + host: str + namespace: Optional[str] = None + + +def get_interface_config(interface: str, sudo: bool = False) -> Optional[str]: + # Execute wg-quick to get the interface config + try: + cmd = ["wg-quick", "strip", interface] + if sudo: + cmd.insert(0, "sudo") + output = subprocess.check_output(cmd, text=True) + except subprocess.CalledProcessError as e: + print(f"Error executing wg-quick: {e}", file=sys.stderr) + return None + + return output + + +def get_addr_maps( + config: str, +) -> List[ + Tuple[PeerMetadata, List[Union[ipaddress.IPv4Address, ipaddress.IPv6Address]]] +]: + # Split into lines + lines = config.splitlines() + + # Read until the first peer definition + while lines and not lines[0].startswith("[Peer]"): + lines.pop(0) + + # Read the peer definitions + output = [] + while len(lines) > 0: + # Read the peer definition + peer_line = lines.pop(0).split("#") + + # Skip peers without metadata + if len(peer_line) == 1 or peer_line[1].strip() == "": + while len(lines) > 0 and not lines[0].startswith("[Peer]"): + lines.pop(0) + continue + + # The metadata is JSON + metadata = json.loads(peer_line[1]) + metadata = PeerMetadata(host=metadata["host"], namespace=metadata.get("ns")) + + # Skim through everything until the next peer definition ( or EOF ) in search of allowed ips + allowed_ips = [] + while len(lines) > 0 and not lines[0].startswith("[Peer]"): + # If this is an allowed ip line, parse it + if lines[0].startswith("AllowedIPs"): + allowed_ips.extend( + [ + ipaddress.ip_network(addr) + for addr in (lines[0].split("=")[1].strip()).split(",") + ] + ) + + # Pop the line + lines.pop(0) + + # Find any ips that are a /32 (ipv4) or /128 (ipv6) + addresses = [] + for allowed_ip in allowed_ips: + if ( + isinstance(allowed_ip, ipaddress.IPv4Network) + and allowed_ip.prefixlen == 32 + ): + addresses.append(allowed_ip.network_address) + elif ( + isinstance(allowed_ip, ipaddress.IPv6Network) + and allowed_ip.prefixlen == 128 + ): + addresses.append(allowed_ip.network_address) + + # Build the output + output.append((metadata, addresses)) + + return output + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="wg-genzone", + description="Generates a DNS zone file for a WireGuard interface", + ) + ap.add_argument("interface", help="The name of the WireGuard interface") + ap.add_argument("--zone", help="The name of the zone to generate", required=True) + ap.add_argument( + "--no-sudo", action="store_true", help="Do not use sudo to execute wg-quick" + ) + args = ap.parse_args() + + # Read the interface config + config = get_interface_config(args.interface, sudo=not args.no_sudo) + if not config: + return 1 + + # Get a mapping of metadata to addresses + addr_maps = get_addr_maps(config) + + # Convert to a zone file + print(f"$ORIGIN {args.zone}.") + print(f"$TTL 60") + print(f"@ IN SOA ns.{args.zone}. noc.ewpratten.com. 1 3600 600 86400 60") + + # Add the hosts + for metadata, addresses in addr_maps: + # Build the host's address + host = metadata.host + if metadata.namespace: + host = f"{host}.{metadata.namespace}" + host = f"{host}.{args.zone}." + + # Add forward and reverse records + for address in addresses: + if isinstance(address, ipaddress.IPv4Address): + print(f"{host} IN A {address}") + print(f"{address.reverse_pointer} IN PTR {host}") + elif isinstance(address, ipaddress.IPv6Address): + print(f"{host} IN AAAA {address}") + print(f"{address.reverse_pointer} IN PTR {host}") + + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/install.conf.yaml b/install.conf.yaml index 0f298ac..ce8f30b 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -49,6 +49,7 @@ ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py ~/bin/guru-vpn: configs/scripts/guru-vpn.py ~/bin/wg-handshakes: configs/scripts/wg-handshakes.py + ~/bin/wg-genzone: configs/scripts/wg-genzone.py # Nautilus right-click scripts ~/.local/share/nautilus/scripts/Copy to web: From 5f312f96abcffc71a26e32a0fab6668b2ae61135 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:28:39 -0400 Subject: [PATCH 138/326] strip --- configs/scripts/wg-genzone.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index b67cd7b..f1c1709 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -63,7 +63,7 @@ def get_addr_maps( if lines[0].startswith("AllowedIPs"): allowed_ips.extend( [ - ipaddress.ip_network(addr) + ipaddress.ip_network(addr.strip()) for addr in (lines[0].split("=")[1].strip()).split(",") ] ) From be5a6fde602c414565270fbca6a62075dbd596f3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:29:33 -0400 Subject: [PATCH 139/326] ignore comments --- configs/scripts/wg-genzone.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index f1c1709..f558836 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -61,10 +61,11 @@ def get_addr_maps( while len(lines) > 0 and not lines[0].startswith("[Peer]"): # If this is an allowed ip line, parse it if lines[0].startswith("AllowedIPs"): + allowed_ips_line = lines[0].split("#")[0] allowed_ips.extend( [ ipaddress.ip_network(addr.strip()) - for addr in (lines[0].split("=")[1].strip()).split(",") + for addr in (allowed_ips_line.split("=")[1].strip()).split(",") ] ) From 9fa0dc0653bb143231242ef51a6a79e292804bea Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:41:35 -0400 Subject: [PATCH 140/326] abs names --- configs/scripts/wg-genzone.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index f558836..c731010 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -124,16 +124,16 @@ def main() -> int: host = metadata.host if metadata.namespace: host = f"{host}.{metadata.namespace}" - host = f"{host}.{args.zone}." + host = f"{host}.{args.zone}" # Add forward and reverse records for address in addresses: if isinstance(address, ipaddress.IPv4Address): - print(f"{host} IN A {address}") - print(f"{address.reverse_pointer} IN PTR {host}") + print(f"{host}. IN A {address}.") + print(f"{address.reverse_pointer}. IN PTR {host}.") elif isinstance(address, ipaddress.IPv6Address): - print(f"{host} IN AAAA {address}") - print(f"{address.reverse_pointer} IN PTR {host}") + print(f"{host}. IN AAAA {address}.") + print(f"{address.reverse_pointer}. IN PTR {host}.") return 0 From 7e2919a59d6d80bd7a4b2fc93a14d52a552c344c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:43:39 -0400 Subject: [PATCH 141/326] ttl --- configs/scripts/wg-genzone.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index c731010..7a3e9be 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -103,6 +103,7 @@ def main() -> int: ap.add_argument( "--no-sudo", action="store_true", help="Do not use sudo to execute wg-quick" ) + ap.add_argument("--ttl", help="The TTL to use for the zone", default=60) args = ap.parse_args() # Read the interface config @@ -115,7 +116,6 @@ def main() -> int: # Convert to a zone file print(f"$ORIGIN {args.zone}.") - print(f"$TTL 60") print(f"@ IN SOA ns.{args.zone}. noc.ewpratten.com. 1 3600 600 86400 60") # Add the hosts @@ -129,11 +129,11 @@ def main() -> int: # Add forward and reverse records for address in addresses: if isinstance(address, ipaddress.IPv4Address): - print(f"{host}. IN A {address}.") - print(f"{address.reverse_pointer}. IN PTR {host}.") + print(f"{host}. {args.ttl} IN A {address}.") + print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}.") elif isinstance(address, ipaddress.IPv6Address): - print(f"{host}. IN AAAA {address}.") - print(f"{address.reverse_pointer}. IN PTR {host}.") + print(f"{host}. {args.ttl} IN AAAA {address}.") + print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}.") return 0 From 8fc198d06476070f0baa08cf12faa485d2d16542 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:50:08 -0400 Subject: [PATCH 142/326] test --- configs/scripts/wg-genzone.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index 7a3e9be..37c30cd 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -116,6 +116,7 @@ def main() -> int: # Convert to a zone file print(f"$ORIGIN {args.zone}.") + print(f"$TTL {args.ttl}") print(f"@ IN SOA ns.{args.zone}. noc.ewpratten.com. 1 3600 600 86400 60") # Add the hosts @@ -129,11 +130,11 @@ def main() -> int: # Add forward and reverse records for address in addresses: if isinstance(address, ipaddress.IPv4Address): - print(f"{host}. {args.ttl} IN A {address}.") - print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}.") + print(f"{host}. IN A {args.ttl} {address}.") + print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}") elif isinstance(address, ipaddress.IPv6Address): print(f"{host}. {args.ttl} IN AAAA {address}.") - print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}.") + print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}") return 0 From 0bdcd2f3f9c6cd9f306e140c586f4463f70a957f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:50:21 -0400 Subject: [PATCH 143/326] test2 --- configs/scripts/wg-genzone.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index 37c30cd..2698e02 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -130,10 +130,10 @@ def main() -> int: # Add forward and reverse records for address in addresses: if isinstance(address, ipaddress.IPv4Address): - print(f"{host}. IN A {args.ttl} {address}.") + print(f"{host}. IN A {args.ttl} {address}") print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}") elif isinstance(address, ipaddress.IPv6Address): - print(f"{host}. {args.ttl} IN AAAA {address}.") + print(f"{host}. {args.ttl} IN AAAA {address}") print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}") From 2ebfed33780c4b82f449f082f8831a19cad6fbe7 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:52:15 -0400 Subject: [PATCH 144/326] rm ttl --- configs/scripts/wg-genzone.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index 2698e02..337b1f6 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -130,11 +130,11 @@ def main() -> int: # Add forward and reverse records for address in addresses: if isinstance(address, ipaddress.IPv4Address): - print(f"{host}. IN A {args.ttl} {address}") - print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}") + print(f"{host}. IN A {address}") + print(f"{address.reverse_pointer}. IN PTR {host}") elif isinstance(address, ipaddress.IPv6Address): - print(f"{host}. {args.ttl} IN AAAA {address}") - print(f"{address.reverse_pointer}. {args.ttl} IN PTR {host}") + print(f"{host}. IN AAAA {address}") + print(f"{address.reverse_pointer}. IN PTR {host}") return 0 From 329ed64cc4b1deb05fde39417575deb8881bbe3b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 13 Oct 2023 13:53:50 -0400 Subject: [PATCH 145/326] abs ptr --- configs/scripts/wg-genzone.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone.py index 337b1f6..6891568 100755 --- a/configs/scripts/wg-genzone.py +++ b/configs/scripts/wg-genzone.py @@ -131,10 +131,10 @@ def main() -> int: for address in addresses: if isinstance(address, ipaddress.IPv4Address): print(f"{host}. IN A {address}") - print(f"{address.reverse_pointer}. IN PTR {host}") + print(f"{address.reverse_pointer}. IN PTR {host}.") elif isinstance(address, ipaddress.IPv6Address): print(f"{host}. IN AAAA {address}") - print(f"{address.reverse_pointer}. IN PTR {host}") + print(f"{address.reverse_pointer}. IN PTR {host}.") return 0 From 7f29d01f8696064c3471a452dc44f0e06a726ae5 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 14 Oct 2023 18:14:52 -0400 Subject: [PATCH 146/326] slight cleanup --- configs/bash/.bashrc | 18 ++++++++++++++++++ configs/git/.gitconfig | 7 ++++++- configs/git/.mailmap | 7 +++++++ install.conf.yaml | 6 +++++- .../run-logid => solutions/run-logid.sh | 0 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 configs/bash/.bashrc create mode 100644 configs/git/.mailmap rename configs/scripts/run-logid => solutions/run-logid.sh (100%) diff --git a/configs/bash/.bashrc b/configs/bash/.bashrc new file mode 100644 index 0000000..19ec4c7 --- /dev/null +++ b/configs/bash/.bashrc @@ -0,0 +1,18 @@ +# This is a somewhat hacky bashrc that is used to provide some of the conveniences from my zshrc on machines that I can't get zsh on +export EWCONFIG_ROOT="$HOME/.config/ewconfig" + +# I always want my ~/bin to be in my PATH +export PATH="$HOME/bin:$PATH" +export PATH="$HOME/.local/bin:$PATH" + +# Makes a directory, then moves into it +mkcd() { + if [ $# != 1 ]; then + echo "Usage: mkcd " + else + mkdir -p $1 && cd $1 + fi +} + +# A basic prompt to display user@host dir sign +export PS1="(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index a2f753e..65aafc9 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -17,6 +17,9 @@ [alias] authors = shortlog --summary --numbered --email + tree = log --graph --decorate --abbrev-commit --all \ + --pretty=format:'%C(auto,yellow)commit %h%C(auto,cyan)%d%n%C(auto,cyan)Author:%Creset %aN <%aE>%n%C(auto,cyan)Date:%Creset %ad%n%s%n' \ + --date=format:'%b %d %Y %H:%M:%S %z' [filter "lfs"] clean = git-lfs clean -- %f @@ -25,7 +28,6 @@ required = true [url "ssh://git@github.com/"] - #insteadOf = https://github.com/ pushInsteadOf = https://github.com/ [credential "https://github.com"] @@ -41,3 +43,6 @@ smtpuser = evan@ewpratten.com smtpencryption = tls smtpserverport = 587 + +[mailmap] + file = ~/.config/git/.mailmap diff --git a/configs/git/.mailmap b/configs/git/.mailmap new file mode 100644 index 0000000..992bb9a --- /dev/null +++ b/configs/git/.mailmap @@ -0,0 +1,7 @@ +Evan Pratten +Evan Pratten +William Meathrel +Carter Tomlenovich +James Nickoli +Sam Lownie +Sam Lownie <30960735+slownie@users.noreply.github.com> \ No newline at end of file diff --git a/install.conf.yaml b/install.conf.yaml index ce8f30b..bc61213 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -18,6 +18,7 @@ - ~/.config/logid - ~/.config/systemd/user - ~/.config/autostart + - ~/.config/git - ~/.cargo - ~/.config/user-tmpfiles.d # Program plugins @@ -27,12 +28,16 @@ - link: # Git ~/.gitconfig: configs/git/.gitconfig + ~/.config/git/.mailmap: configs/git/.mailmap ~/.ssh/allowed_signers: configs/ssh/allowed_signers # Shell ~/.zshrc: path: configs/zsh/.zshrc force: true + ~/.bashrc: + path: configs/bash/.bashrc + force: true # Vim ~/.config/nvim/init.vim: configs/nvim/init.vim @@ -43,7 +48,6 @@ ~/bin/catto: configs/scripts/catto ~/bin/aspath: configs/scripts/aspath ~/bin/fetch-steamdeck-screenshots: configs/scripts/fetch-steamdeck-screenshots - ~/bin/run-logid: configs/scripts/run-logid ~/bin/houdini-tool: configs/scripts/houdini-tool.py ~/bin/hython-latest: configs/scripts/hython-latest ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py diff --git a/configs/scripts/run-logid b/solutions/run-logid.sh similarity index 100% rename from configs/scripts/run-logid rename to solutions/run-logid.sh From 7b66e8b3976d8367d131dff5cd1bff669ecc041c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 15 Oct 2023 14:30:52 -0400 Subject: [PATCH 147/326] Add services --- install.conf.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/install.conf.yaml b/install.conf.yaml index bc61213..ffe62ef 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -9,6 +9,7 @@ - ~/Downloads - ~/bin - ~/projects + - ~/services - ~/src - ~/www - ~/pkg From 056ccf3c36d1f1cf349b37f086e40f1823b22902 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 15 Oct 2023 16:32:59 -0400 Subject: [PATCH 148/326] sendmail script --- configs/scripts/ewp-sendmail.py | 66 +++++++++++++++++++++++++++++++++ install.conf.yaml | 1 + 2 files changed, 67 insertions(+) create mode 100644 configs/scripts/ewp-sendmail.py diff --git a/configs/scripts/ewp-sendmail.py b/configs/scripts/ewp-sendmail.py new file mode 100644 index 0000000..8bdf55a --- /dev/null +++ b/configs/scripts/ewp-sendmail.py @@ -0,0 +1,66 @@ +#! /usr/bin/env python3 +import smtplib +import getpass +from email.message import EmailMessage +import argparse +import sys + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="ewp-sendmail", description="Easily send real emails" + ) + ap.add_argument( + "--recipient", + "--to", + help="Email address of the recipient", + default="evan@ewpratten.com", + ) + ap.add_argument("--cc", help="Email addresses to CC", nargs="+") + ap.add_argument("--subject", "-s", help="Subject of the email") + ap.add_argument( + "--from", + help="Sender of the email", + default="system-reports@ewpratten.com", + dest="sender", + ) + ap.add_argument( + "--password", + help="Password to use for sending the email. Overrides the password in ~/.netrc", + ) + args = ap.parse_args() + + # Read the body from stdin + print("Enter the body of the email. Press Ctrl+D when done.") + body = sys.stdin.read() + + # Read the password + password = args.password or getpass.getpass(f"Password for {args.sender}: ") + + # Log in to the SMTP server + print("Connecting to SMTP server...") + smtp = smtplib.SMTP("smtp.ewpratten.com", 587) + smtp.ehlo() + smtp.starttls() + print("Authenticating...") + smtp.login(args.sender, password) + print("Sending email...") + # Create the email + msg = EmailMessage() + msg.set_content(body) + msg["Subject"] = args.subject + msg["From"] = args.sender + msg["To"] = args.recipient + if args.cc: + msg["Cc"] = ",".join(args.cc) + # Send the email + smtp.send_message(msg) + print("Done.") + smtp.quit() + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/install.conf.yaml b/install.conf.yaml index ffe62ef..03558af 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -55,6 +55,7 @@ ~/bin/guru-vpn: configs/scripts/guru-vpn.py ~/bin/wg-handshakes: configs/scripts/wg-handshakes.py ~/bin/wg-genzone: configs/scripts/wg-genzone.py + ~/bin/ewp-sendmail: configs/scripts/ewp-sendmail.py # Nautilus right-click scripts ~/.local/share/nautilus/scripts/Copy to web: From 9acacb23d1aa0c6422f43b72a727045966bca89c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 15 Oct 2023 16:58:53 -0400 Subject: [PATCH 149/326] Add blender addon --- .../3.x/scripts/addons/y_aligned_camera.py | 54 +++++++++++++++++++ configs/scripts/ewp-sendmail.py | 0 install.conf.yaml | 4 ++ 3 files changed, 58 insertions(+) create mode 100644 configs/blender/3.x/scripts/addons/y_aligned_camera.py mode change 100644 => 100755 configs/scripts/ewp-sendmail.py diff --git a/configs/blender/3.x/scripts/addons/y_aligned_camera.py b/configs/blender/3.x/scripts/addons/y_aligned_camera.py new file mode 100644 index 0000000..0216a4f --- /dev/null +++ b/configs/blender/3.x/scripts/addons/y_aligned_camera.py @@ -0,0 +1,54 @@ +bl_info = { + "name": "Evan's Y-aligned Camera Creator", + "author": "Evan Pratten ", + "version": (1, 0), + "blender": (3, 0, 0), + "description": "Adds a camera that is aligned with the Y axis by default", + "category": "General", +} + +import bpy +from bpy.types import Operator +from bpy_extras.object_utils import AddObjectHelper +import math + + +class OBJECT_OT_add_object(Operator, AddObjectHelper): + """Create a new Camera Object facing +Y""" + + bl_idname = "mesh.add_y_camera" + bl_label = "Add Camera Object facing +Y" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, _): + print("[+Y Camera] Creating new camera and adding to scene at origin") + + # Create a new camera, facing +Y + camera_data = bpy.data.cameras.new(name="Camera") + camera_object = bpy.data.objects.new("Camera", camera_data) + camera_object.rotation_euler[0] = math.radians(90) + + # Add the camera to the scene + bpy.context.scene.collection.objects.link(camera_object) + + return {"FINISHED"} + + +def blender_button_add_y_camera(obj, _): + obj.layout.operator( + OBJECT_OT_add_object.bl_idname, text="+Y Camera", icon="CAMERA_DATA" + ) + + +def register(): + bpy.utils.register_class(OBJECT_OT_add_object) + bpy.types.VIEW3D_MT_add.append( + lambda obj, ctx: blender_button_add_y_camera(obj, ctx) + ) + + +def unregister(): + bpy.utils.unregister_class(OBJECT_OT_add_object) + bpy.types.VIEW3D_MT_add.remove( + lambda obj, ctx: blender_button_add_y_camera(obj, ctx) + ) diff --git a/configs/scripts/ewp-sendmail.py b/configs/scripts/ewp-sendmail.py old mode 100644 new mode 100755 diff --git a/install.conf.yaml b/install.conf.yaml index 03558af..ef3edea 100644 --- a/install.conf.yaml +++ b/install.conf.yaml @@ -22,6 +22,7 @@ - ~/.config/git - ~/.cargo - ~/.config/user-tmpfiles.d + - ~/.config/blender/3.6/scripts/addons # Program plugins - ~/.local/share/nautilus/scripts/ - ~/houdini19.5 @@ -72,6 +73,9 @@ ~/.config/autostart/gnome-keyring-ssh.desktop: configs/autostart/gnome-keyring-ssh.desktop ~/.config/autostart/logid.desktop: configs/autostart/logid.desktop + # Blender Addons + ~/.config/blender/3.6/scripts/addons/y_aligned_camera.py: configs/blender/3.x/scripts/addons/y_aligned_camera.py + # Others ~/.config/tabset: configs/tabset ~/.config/rofi: configs/rofi From d9bbceb74d667c44ce1c4be70ef0fe2e585d6710 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 16 Oct 2023 11:30:23 -0400 Subject: [PATCH 150/326] fix ewconfig-pull --- configs/pkcs11/modules/opensc.module | 12 ------------ configs/zsh/macros.sh | 9 ++++++++- 2 files changed, 8 insertions(+), 13 deletions(-) delete mode 100644 configs/pkcs11/modules/opensc.module diff --git a/configs/pkcs11/modules/opensc.module b/configs/pkcs11/modules/opensc.module deleted file mode 100644 index 9cb6765..0000000 --- a/configs/pkcs11/modules/opensc.module +++ /dev/null @@ -1,12 +0,0 @@ -# This file describes how to load the opensc module -# See: https://p11-glue.github.io/p11-glue/p11-kit/manual/pkcs11-conf.html -# or man pkcs11.conf - -# This is a relative path, which means it will be loaded from -# the p11-kit default path which is usually $(libdir)/pkcs11. -# Doing it this way allows for packagers to package opensc for -# 32-bit and 64-bit and make them parallel installable -module: opensc-pkcs11.so - -# Disables annoying password popup when a Yubikey is left plugged in to a system -disable-in: firefox vivaldi-bin thunderbird diff --git a/configs/zsh/macros.sh b/configs/zsh/macros.sh index 41869fc..78342e9 100644 --- a/configs/zsh/macros.sh +++ b/configs/zsh/macros.sh @@ -14,7 +14,6 @@ alias sheridan-rdp='firefox --new-window "ext+container:name=College&url=https:/ alias git-diff-nvim="git diff | nvim -R -d -c 'set filetype=diff' -" alias yk-totp="ykman oath accounts code" alias flush-dns-cache="sudo systemd-resolve --flush-caches" -alias ewconfig-pull="cd ~/.config/ewconfig; git pull" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" @@ -167,3 +166,11 @@ proc-grep() { ps aux | { head -1; grep $1 } fi } + +# Updates ewconfig +ewconfig-pull() { + cwd=$(pwd) + cd ~/.config/ewconfig + git pull + cd $cwd +} \ No newline at end of file From 03f8da229f7f90847db25357e5abd0eb2736f3ab Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 16 Oct 2023 14:45:57 -0400 Subject: [PATCH 151/326] Change some git aliases --- configs/git/.gitconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 65aafc9..aa4acf2 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -18,8 +18,9 @@ [alias] authors = shortlog --summary --numbered --email tree = log --graph --decorate --abbrev-commit --all \ - --pretty=format:'%C(auto,yellow)commit %h%C(auto,cyan)%d%n%C(auto,cyan)Author:%Creset %aN <%aE>%n%C(auto,cyan)Date:%Creset %ad%n%s%n' \ + --pretty=format:'%C(yellow)commit %h%C(auto)%d%n%C(cyan)Author:%Creset %aN %C(dim white)<%aE>%n%C(cyan)Date:%Creset %C(dim white)%ad (%ar)%n%s%n' \ --date=format:'%b %d %Y %H:%M:%S %z' + branches = branch -a -l -vv [filter "lfs"] clean = git-lfs clean -- %f From 1725e8682edd9aa379e48049ad4fed631d6593d6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:30:22 -0400 Subject: [PATCH 152/326] rm dotbot --- .gitmodules | 4 ---- dotbot | 1 - 2 files changed, 5 deletions(-) delete mode 160000 dotbot diff --git a/.gitmodules b/.gitmodules index 2342512..6558645 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "dotbot"] - path = dotbot - url = https://github.com/anishathalye/dotbot - ignore = dirty [submodule "configs/nvim/pack/tpope/start/repeat"] path = configs/nvim/pack/tpope/start/repeat url = https://tpope.io/vim/repeat.git diff --git a/dotbot b/dotbot deleted file mode 160000 index 769767c..0000000 --- a/dotbot +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 769767c129c8f26eb66dca06dfa4a1bddbac8a9e From ea6968019c4f45a5fe07906d03351d8d4d5d45c4 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:30:32 -0400 Subject: [PATCH 153/326] reorg everything to not need dotbot --- .vscode/tasks.json | 5 +- README.md | 9 +- configs/autostart/gnome-keyring-ssh.desktop | 157 ------------------ configs/autostart/logid.desktop | 7 - configs/git/.gitconfig | 17 +- .../enable-signing.gitconfig | 0 .../config-fragments/personal-info.gitconfig | 10 ++ configs/nvim/pack/pack | 1 + configs/nvim/third_party/third_party | 1 + configs/rofi/rofi | 1 + .../scripts/configure-gnome-remote-desktop | 0 .../scripts/{ewp-sendmail.py => ewp-sendmail} | 0 configs/scripts/{guru-vpn.py => guru-vpn} | 0 .../scripts/{houdini-tool.py => houdini-tool} | 0 .../run-logid.sh => configs/scripts/run-logid | 0 .../scripts/{usdnc-to-usd.py => usdnc-to-usd} | 0 .../{video_trimmer.py => video_trimmer} | 0 configs/scripts/{wg-genzone.py => wg-genzone} | 0 .../{wg-handshakes.py => wg-handshakes} | 0 configs/{ => shells}/bash/.bashrc | 13 +- configs/{zsh => shells/bash}/macros.sh | 9 - configs/{ => shells}/zsh/.zshrc | 13 +- configs/{ => shells}/zsh/autocomplete.sh | 0 configs/{ => shells}/zsh/info.sh | 0 configs/{ => shells}/zsh/keybinds.sh | 0 configs/shells/zsh/macros.sh | 11 ++ configs/{ => shells}/zsh/prompt.sh | 0 configs/tabset/tabset | 1 + configs/zsh/by_host/ewpratten-laptop.sh | 16 -- helpers/git-config-features.sh | 7 - helpers/install-ssh-config.sh | 13 -- install | 15 -- install-linux.sh | 120 +++++++++++++ install-windows.sh | 40 +++++ 34 files changed, 212 insertions(+), 254 deletions(-) delete mode 100644 configs/autostart/gnome-keyring-ssh.desktop delete mode 100644 configs/autostart/logid.desktop rename configs/git/{features => config-fragments}/enable-signing.gitconfig (100%) create mode 100644 configs/git/config-fragments/personal-info.gitconfig create mode 120000 configs/nvim/pack/pack create mode 120000 configs/nvim/third_party/third_party create mode 120000 configs/rofi/rofi rename solutions/configure-gnome-remote-desktop.sh => configs/scripts/configure-gnome-remote-desktop (100%) rename configs/scripts/{ewp-sendmail.py => ewp-sendmail} (100%) rename configs/scripts/{guru-vpn.py => guru-vpn} (100%) rename configs/scripts/{houdini-tool.py => houdini-tool} (100%) rename solutions/run-logid.sh => configs/scripts/run-logid (100%) rename configs/scripts/{usdnc-to-usd.py => usdnc-to-usd} (100%) rename configs/scripts/{video_trimmer.py => video_trimmer} (100%) rename configs/scripts/{wg-genzone.py => wg-genzone} (100%) rename configs/scripts/{wg-handshakes.py => wg-handshakes} (100%) rename configs/{ => shells}/bash/.bashrc (72%) rename configs/{zsh => shells/bash}/macros.sh (96%) rename configs/{ => shells}/zsh/.zshrc (74%) rename configs/{ => shells}/zsh/autocomplete.sh (100%) rename configs/{ => shells}/zsh/info.sh (100%) rename configs/{ => shells}/zsh/keybinds.sh (100%) create mode 100644 configs/shells/zsh/macros.sh rename configs/{ => shells}/zsh/prompt.sh (100%) create mode 120000 configs/tabset/tabset delete mode 100644 configs/zsh/by_host/ewpratten-laptop.sh delete mode 100644 helpers/git-config-features.sh delete mode 100644 helpers/install-ssh-config.sh delete mode 100755 install create mode 100644 install-linux.sh create mode 100644 install-windows.sh diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 54e38d5..0b5a47e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,7 +6,10 @@ { "label": "Run install script", "type": "shell", - "command": "./install", + "command": "sh", + "args": [ + "./install-linux.sh" + ], "problemMatcher": [] } ] diff --git a/README.md b/README.md index 7856aaf..c57062e 100644 --- a/README.md +++ b/README.md @@ -16,5 +16,10 @@ Install and link everything with: mkdir -p ~/.config && cd ~/.config git clone https://github.com/ewpratten/ewconfig cd ewconfig -./install -``` \ No newline at end of file + +# Linux +sh ./install-linux.sh + +# Windows, with GIT BASH +sh ./install-windows.sh +``` diff --git a/configs/autostart/gnome-keyring-ssh.desktop b/configs/autostart/gnome-keyring-ssh.desktop deleted file mode 100644 index a46a76a..0000000 --- a/configs/autostart/gnome-keyring-ssh.desktop +++ /dev/null @@ -1,157 +0,0 @@ -[Desktop Entry] -Hidden=true -Type=Application -Name[af]=SSH-sleutelagent -Name[ar]=عميل مفاتيح SSH -Name[as]=SSH কি সহায়ক -Name[ast]=Axente de claves SSH -Name[be]=SSH-агент ключоў -Name[bg]=Агентът на SSH за ключове -Name[bn]=SSH কী এজেন্ট -Name[bn_IN]=SSH কি এজেন্ট -Name[bs]=Agent za SSH ključeve -Name[ca]=Agent de claus SSH -Name[ca@valencia]=Agent de claus SSH -Name[cs]=Agent klíčů SSH -Name[da]=SSH-nøgleagent -Name[de]=SSH-Schlüsselagent -Name[el]=Πράκτορας κλειδιού SSH -Name[en_GB]=SSH Key Agent -Name[eo]=SSH-ŝlosila agento -Name[es]=Agente de claves SSH -Name[et]=SSH-võtmete agent -Name[eu]=SSH gako-agentea -Name[fa]=عامل کلید SSH -Name[fi]=SSH-avainten agentti -Name[fr]=Agent de clés SSH -Name[fur]=Agjent clâfs SSH -Name[gd]=Àidseant iuchair SSH -Name[gl]=Axente de chave SSH -Name[gu]=SSH કી ઍજન્ટ -Name[he]=סוכן מפתחות SSH -Name[hi]=AFS कुँजी प्रतिनिधि -Name[hr]=Agent SSH ključa -Name[hu]=SSH-kulcs ügynök -Name[id]=Agen Kunci SSH -Name[it]=Agente chiavi SSH -Name[ja]=SSH 鍵エージェント -Name[kk]=SSH кілттер агенті -Name[km]=ភ្នាក់ងារ​សោ SSH -Name[kn]=SSH ಕೀಲಿ ಮಧ್ಯವರ್ತಿ -Name[ko]=SSH 키 에이전트 -Name[lt]=SSH raktų tarnyba -Name[lv]=SSH atslēgu aģents -Name[mjw]=SSH Key Agent -Name[mk]=Агент за SSH клучеви -Name[ml]=എസ്എസ്എച് കീ ഏജന്റ് -Name[mr]=SSH कि एजंट -Name[ms]=Ejen Kunci SSH -Name[nb]=SSH-nøkkelagent -Name[nl]=SSH-sleutelagent -Name[nn]=Nøkkelagent for SSH -Name[oc]=Agent de claus SSH -Name[or]=SSH କି ସଦସ୍ୟ -Name[pa]=SSH ਕੁੰਜੀ ਏਜੰਟ -Name[pl]=Agent kluczy SSH -Name[pt]=Agente de chaves SSH -Name[pt_BR]=Agente de chaves SSH -Name[ro]=Agent pentru chei SSH -Name[ru]=Агент ключей SSH -Name[sk]=Agent kľúčov SSH -Name[sl]=Agent ključev SSH -Name[sr]=Агент за ССХ кључеве -Name[sr@latin]=Agent za SSH ključeve -Name[sv]=SSH-nyckelagent -Name[ta]=SSH முகவர் -Name[te]=SSH కీ వాహకము -Name[th]=เอเจนต์กุญแจ SSH -Name[tr]=SSH Anahtar Aracı -Name[ug]=SSH ئاچقۇچ ياردەمچىسى -Name[uk]=Агент ключів SSH -Name[vi]=Đại diện khóa SSH -Name[zh_CN]=SSH 密钥代理 -Name[zh_HK]=SSH 密碼匙代理程式 -Name[zh_TW]=SSH 金鑰代理程式 -Name=SSH Key Agent -Comment[af]=GNOME-sleutelring: SSH-agent -Comment[ar]=حلقة مفاتيح جنوم: عميل SSH -Comment[as]=GNOME Keyring: SSH সহায়ক -Comment[ast]=Depósitu de claves de GNOME: axente SSH -Comment[be]=Вязкі ключоў GNOME: SSH-агент -Comment[bg]=Ключодържател на GNOME: агент на SSH -Comment[bn]=GNOME কী রিং: SSH এজেন্ট -Comment[bn_IN]=GNOME Keyring: SSH এজেন্ট -Comment[bs]=Gnomovi privjesci: SSH agent -Comment[ca]=Anell de claus del GNOME: agent SSH -Comment[ca@valencia]=Anell de claus del GNOME: agent SSH -Comment[cs]=Klíčenka GNOME: Agent SSH -Comment[da]=GNOME-nøgleringsdæmon: SSH-agent -Comment[de]=GNOME-Schlüsselbunddienst: SSH-Agent -Comment[el]=Κλειδοθήκη GNOME: Πράκτορας SSH -Comment[en_GB]=GNOME Keyring: SSH Agent -Comment[eo]=GNOME Ŝlosilaro: SSH-agento -Comment[es]=Depósito de claves de GNOME: agente SSH -Comment[et]=GNOME võtmerõngas: SSH-agent -Comment[eu]=GNOMEren gako-sorta: SSH agentea -Comment[fa]=دسته‌کلید گنوم: عامل SSH -Comment[fi]=Gnomen avainnippu: SSH-agentti -Comment[fr]=Trousseau de clés de GNOME : agent SSH -Comment[fur]=Puarteclâfs di GNOME: agjent SSH -Comment[gd]=Dul-iuchrach: Àidseant SSH -Comment[gl]=GNOME Keyring: Axente SSH -Comment[gu]=GNOME કીરીંગ: SSH ઍજન્ટ -Comment[he]=קבוצת מפתחות של GNOME: סוכן SSH -Comment[hi]=गनोम कीरिंग: SSH प्रतिनिधि -Comment[hr]=GNOME skup ključeva: SSH agent -Comment[hu]=GNOME kulcstartó – SSH-ügynök -Comment[id]=Ring Kunci GNOME: Agen SSH -Comment[it]=Portachiavi di GNOME: agente SSH -Comment[ja]=GNOME キーリング: SSH エージェント -Comment[kk]=GNOME Keyring: SSH агенті -Comment[km]=GNOME Keyring ៖ ភ្នាក់ងារ SSH -Comment[kn]=GNOME ಕೀಲಿಗೊಂಚಲು: SSH ಮಧ್ಯವರ್ತಿ -Comment[ko]=그놈 키 모음: SSH 에이전트 -Comment[lt]=GNOME raktinė: SSH tarnyba -Comment[lv]=GNOME atslēgu saišķis — SSH aģents -Comment[mjw]=GNOME Keyring: SSH Agent -Comment[mk]=Приврзок на GNOME: SSH агент -Comment[ml]=ഗ്നോം കീറിങ്: എസ്എസ്എച് ഏജന്റ് -Comment[mr]=GNOME किरिंग: SSH एजंट -Comment[ms]=Gelang Kunci GNOME: Ejen SSH -Comment[nb]=GNOME nøkkelring: SSH-agent -Comment[ne]=जिनोम किरिङ : SSH एजेन्ट -Comment[nl]=Sleutelbos-service: SSH-agent -Comment[nn]=GNOME Nøkkelring: SSH-agent -Comment[oc]=Trossèl de claus GNOME : agent SSH -Comment[or]=GNOME କି ରିଙ୍ଗ: SSH ସଦସ୍ୟ -Comment[pa]=ਗਨੋਮ ਕੀਰਿੰਗ: SSH ਏਜੰਟ -Comment[pl]=Baza kluczy dla środowiska GNOME: agent SSH -Comment[pt]=GNOME Keyring: agente SSH -Comment[pt_BR]=Chaveiro do GNOME: Agente SSH -Comment[ro]=Inelul de chei GNOME: Agent SSH -Comment[ru]=Связка ключей GNOME: SSH-агент -Comment[sk]=SSH agent zväzku kľúčov GNOME -Comment[sl]=Zbirka ključev GNOME: agent SSH -Comment[sr]=Гномови привесци: ССХ агент -Comment[sr@latin]=Gnomovi privesci: SSH agent -Comment[sv]=GNOME-nyckelring: SSH-agent -Comment[ta]=GNOME கீரிங்: SSH முகவர் -Comment[te]=GNOME కీరింగ్: SSH వాహకం -Comment[th]=พวงกุญแจของ GNOME: เอเจนต์ SSH -Comment[tr]=GNOME Anahtarlığı: SSH Aracı -Comment[ug]=گىنوم ئاچقۇچ ھالقىسى:SSH ياردەمچىسى -Comment[uk]=Служба в'язки ключів GNOME: агент SSH -Comment[vi]=Chùm chìa khóa GNOME: Đại diện SSH -Comment[zh_CN]=GNOME 密钥环:SSH 代理 -Comment[zh_HK]=GNOME 密碼匙圈:SSH 代理程式 -Comment[zh_TW]=GNOME 鑰匙圈:SSH 代理程式 -Comment=GNOME Keyring: SSH Agent -Exec=/usr/bin/gnome-keyring-daemon --start --components=ssh -OnlyShowIn=GNOME;Unity;MATE; -X-GNOME-Autostart-Phase=PreDisplayServer -X-GNOME-AutoRestart=false -X-GNOME-Autostart-Notify=true -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=gnome-keyring -X-GNOME-Bugzilla-Component=general -X-GNOME-Bugzilla-Version=42.1 diff --git a/configs/autostart/logid.desktop b/configs/autostart/logid.desktop deleted file mode 100644 index acaaf24..0000000 --- a/configs/autostart/logid.desktop +++ /dev/null @@ -1,7 +0,0 @@ -[Desktop Entry] -Name = Logid -GenericName = Logid -Comment = Logitech Mouse Driver -Exec = logid -v -c $HOME/.config/logid/logid.cfg -Type = Application -X-GNOME-Autostart-enabled = false diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index aa4acf2..e113bf8 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -1,10 +1,9 @@ [include] - path = ~/.config/git/features/enable-signing.gitconfig - -[user] - email = evan@ewpratten.com - name = Evan Pratten - signingkey = ~/.ssh/id_ed25519_sk_rk_yk20572395 + # NOTE: These paths are imported if they exist and ignored if they don't + # This allows us to have a single config file for all our machines + # and control the specifics by symlinking the relevant files per-machine + path = ~/.config/git/config-fragments/personal-info.gitconfig + path = ~/.config/git/config-fragments/enable-signing.gitconfig [init] defaultBranch = master @@ -39,11 +38,5 @@ helper = helper = !/usr/bin/gh auth git-credential -[sendemail] - smtpserver = smtp.migadu.com - smtpuser = evan@ewpratten.com - smtpencryption = tls - smtpserverport = 587 - [mailmap] file = ~/.config/git/.mailmap diff --git a/configs/git/features/enable-signing.gitconfig b/configs/git/config-fragments/enable-signing.gitconfig similarity index 100% rename from configs/git/features/enable-signing.gitconfig rename to configs/git/config-fragments/enable-signing.gitconfig diff --git a/configs/git/config-fragments/personal-info.gitconfig b/configs/git/config-fragments/personal-info.gitconfig new file mode 100644 index 0000000..1b89904 --- /dev/null +++ b/configs/git/config-fragments/personal-info.gitconfig @@ -0,0 +1,10 @@ +[user] + email = evan@ewpratten.com + name = Evan Pratten + signingkey = ~/.ssh/id_ed25519_sk_rk_yk20572395 + +[sendemail] + smtpserver = smtp.migadu.com + smtpuser = evan@ewpratten.com + smtpencryption = tls + smtpserverport = 587 diff --git a/configs/nvim/pack/pack b/configs/nvim/pack/pack new file mode 120000 index 0000000..7c8b955 --- /dev/null +++ b/configs/nvim/pack/pack @@ -0,0 +1 @@ +/home/ewpratten/.config/ewconfig/configs/nvim/pack \ No newline at end of file diff --git a/configs/nvim/third_party/third_party b/configs/nvim/third_party/third_party new file mode 120000 index 0000000..937284f --- /dev/null +++ b/configs/nvim/third_party/third_party @@ -0,0 +1 @@ +/home/ewpratten/.config/ewconfig/configs/nvim/third_party \ No newline at end of file diff --git a/configs/rofi/rofi b/configs/rofi/rofi new file mode 120000 index 0000000..7be4e32 --- /dev/null +++ b/configs/rofi/rofi @@ -0,0 +1 @@ +/home/ewpratten/.config/ewconfig/configs/rofi/ \ No newline at end of file diff --git a/solutions/configure-gnome-remote-desktop.sh b/configs/scripts/configure-gnome-remote-desktop similarity index 100% rename from solutions/configure-gnome-remote-desktop.sh rename to configs/scripts/configure-gnome-remote-desktop diff --git a/configs/scripts/ewp-sendmail.py b/configs/scripts/ewp-sendmail similarity index 100% rename from configs/scripts/ewp-sendmail.py rename to configs/scripts/ewp-sendmail diff --git a/configs/scripts/guru-vpn.py b/configs/scripts/guru-vpn similarity index 100% rename from configs/scripts/guru-vpn.py rename to configs/scripts/guru-vpn diff --git a/configs/scripts/houdini-tool.py b/configs/scripts/houdini-tool similarity index 100% rename from configs/scripts/houdini-tool.py rename to configs/scripts/houdini-tool diff --git a/solutions/run-logid.sh b/configs/scripts/run-logid similarity index 100% rename from solutions/run-logid.sh rename to configs/scripts/run-logid diff --git a/configs/scripts/usdnc-to-usd.py b/configs/scripts/usdnc-to-usd similarity index 100% rename from configs/scripts/usdnc-to-usd.py rename to configs/scripts/usdnc-to-usd diff --git a/configs/scripts/video_trimmer.py b/configs/scripts/video_trimmer similarity index 100% rename from configs/scripts/video_trimmer.py rename to configs/scripts/video_trimmer diff --git a/configs/scripts/wg-genzone.py b/configs/scripts/wg-genzone similarity index 100% rename from configs/scripts/wg-genzone.py rename to configs/scripts/wg-genzone diff --git a/configs/scripts/wg-handshakes.py b/configs/scripts/wg-handshakes similarity index 100% rename from configs/scripts/wg-handshakes.py rename to configs/scripts/wg-handshakes diff --git a/configs/bash/.bashrc b/configs/shells/bash/.bashrc similarity index 72% rename from configs/bash/.bashrc rename to configs/shells/bash/.bashrc index 19ec4c7..23bf9d4 100644 --- a/configs/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -1,18 +1,13 @@ # This is a somewhat hacky bashrc that is used to provide some of the conveniences from my zshrc on machines that I can't get zsh on export EWCONFIG_ROOT="$HOME/.config/ewconfig" +# Load macros +. $EWCONFIG_ROOT/configs/shells/bash/macros.sh + # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" +export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" -# Makes a directory, then moves into it -mkcd() { - if [ $# != 1 ]; then - echo "Usage: mkcd " - else - mkdir -p $1 && cd $1 - fi -} - # A basic prompt to display user@host dir sign export PS1="(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" diff --git a/configs/zsh/macros.sh b/configs/shells/bash/macros.sh similarity index 96% rename from configs/zsh/macros.sh rename to configs/shells/bash/macros.sh index 78342e9..130c2c5 100644 --- a/configs/zsh/macros.sh +++ b/configs/shells/bash/macros.sh @@ -158,15 +158,6 @@ wg-cat() { fi } -# Search for a process -proc-grep() { - if [ $# != 1 ]; then - echo "Usage: proc-grep " - else - ps aux | { head -1; grep $1 } - fi -} - # Updates ewconfig ewconfig-pull() { cwd=$(pwd) diff --git a/configs/zsh/.zshrc b/configs/shells/zsh/.zshrc similarity index 74% rename from configs/zsh/.zshrc rename to configs/shells/zsh/.zshrc index 60015ff..6df5967 100644 --- a/configs/zsh/.zshrc +++ b/configs/shells/zsh/.zshrc @@ -3,21 +3,22 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" # Load my custom prompt and macros -. $EWCONFIG_ROOT/configs/zsh/prompt.sh -. $EWCONFIG_ROOT/configs/zsh/macros.sh -. $EWCONFIG_ROOT/configs/zsh/keybinds.sh -. $EWCONFIG_ROOT/configs/zsh/autocomplete.sh +. $EWCONFIG_ROOT/configs/shells/zsh/prompt.sh +. $EWCONFIG_ROOT/configs/shells/zsh/macros.sh +. $EWCONFIG_ROOT/configs/shells/zsh/keybinds.sh +. $EWCONFIG_ROOT/configs/shells/zsh/autocomplete.sh # Load per-host configuration if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then - . $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh + . $EWCONFIG_ROOT/configs/shells/zsh/by_host/$HOSTNAME.sh fi # Show some host info -. $EWCONFIG_ROOT/configs/zsh/info.sh +. $EWCONFIG_ROOT/configs/shells/zsh/info.sh # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" +export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" # Configure a sane default editor diff --git a/configs/zsh/autocomplete.sh b/configs/shells/zsh/autocomplete.sh similarity index 100% rename from configs/zsh/autocomplete.sh rename to configs/shells/zsh/autocomplete.sh diff --git a/configs/zsh/info.sh b/configs/shells/zsh/info.sh similarity index 100% rename from configs/zsh/info.sh rename to configs/shells/zsh/info.sh diff --git a/configs/zsh/keybinds.sh b/configs/shells/zsh/keybinds.sh similarity index 100% rename from configs/zsh/keybinds.sh rename to configs/shells/zsh/keybinds.sh diff --git a/configs/shells/zsh/macros.sh b/configs/shells/zsh/macros.sh new file mode 100644 index 0000000..d043a99 --- /dev/null +++ b/configs/shells/zsh/macros.sh @@ -0,0 +1,11 @@ +# We are compatible with bash, so first load the bash-specific macros +. $EWCONFIG_ROOT/configs/shells/bash/macros.sh + +# Search for a process +proc-grep() { + if [ $# != 1 ]; then + echo "Usage: proc-grep " + else + ps aux | { head -1; grep $1 } + fi +} diff --git a/configs/zsh/prompt.sh b/configs/shells/zsh/prompt.sh similarity index 100% rename from configs/zsh/prompt.sh rename to configs/shells/zsh/prompt.sh diff --git a/configs/tabset/tabset b/configs/tabset/tabset new file mode 120000 index 0000000..a3e8e62 --- /dev/null +++ b/configs/tabset/tabset @@ -0,0 +1 @@ +/home/ewpratten/.config/ewconfig/configs/tabset/ \ No newline at end of file diff --git a/configs/zsh/by_host/ewpratten-laptop.sh b/configs/zsh/by_host/ewpratten-laptop.sh deleted file mode 100644 index 2d52610..0000000 --- a/configs/zsh/by_host/ewpratten-laptop.sh +++ /dev/null @@ -1,16 +0,0 @@ -#! /bin/bash - -# Various custom-compiled libs live here -export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH - -# SDKMAN! -export SDKMAN_DIR="$HOME/.sdkman" -[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" - -# NVM -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm -[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion - -# Flutter -export PATH="$PATH:$HOME/development/flutter/bin" diff --git a/helpers/git-config-features.sh b/helpers/git-config-features.sh deleted file mode 100644 index 5736766..0000000 --- a/helpers/git-config-features.sh +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/bash -set -e - -if [[ "$HOSTNAME" == "fedora" ]] || [[ "$HOSTNAME" == "ewpratten-laptop" ]]; then - mkdir -p $HOME/.config/git/features - ln -sf $EWCONFIG_ROOT/configs/git/features/enable-signing.gitconfig $HOME/.config/git/features/enable-signing.gitconfig -fi \ No newline at end of file diff --git a/helpers/install-ssh-config.sh b/helpers/install-ssh-config.sh deleted file mode 100644 index ef1ed14..0000000 --- a/helpers/install-ssh-config.sh +++ /dev/null @@ -1,13 +0,0 @@ -#! /bin/sh -# Installs the SSH config file -set -e - -# Link the SSH config file -echo "Linking SSH config file..." -mkdir -p "$HOME/.ssh" -ln -sf "$(pwd)/configs/ssh/config" "$HOME/.ssh/config" - -# Set the correct permissions -echo "Setting SSH config file permissions..." -chmod 644 "$HOME/.ssh/config" -chown "$USER:$USER" "$HOME/.ssh/config" \ No newline at end of file diff --git a/install b/install deleted file mode 100755 index 5a7e72c..0000000 --- a/install +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set -e - -CONFIG="install.conf.yaml" -DOTBOT_DIR="dotbot" - -DOTBOT_BIN="bin/dotbot" -BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -cd "${BASEDIR}" -git -C "${DOTBOT_DIR}" submodule sync --quiet --recursive -git submodule update --init --recursive "${DOTBOT_DIR}" - -"${BASEDIR}/${DOTBOT_DIR}/${DOTBOT_BIN}" -d "${BASEDIR}" -c "${CONFIG}" "${@}" diff --git a/install-linux.sh b/install-linux.sh new file mode 100644 index 0000000..60aa757 --- /dev/null +++ b/install-linux.sh @@ -0,0 +1,120 @@ +#! /bin/sh +set -e +export EWCONFIG_ROOT=$(dirname $(readlink -f $0)) + +# -- Ensure that deps exist -- + +# Pull git submodules if needed +if type -p git > /dev/null; then + echo "Syncing git submodules..." + git submodule update --init --recursive +fi + +# Make sure scripts are all executable +chmod +x $EWCONFIG_ROOT/configs/scripts/* +chmod +x $EWCONFIG_ROOT/configs/nautilus/scripts/* + +# -- Directory Setup -- +set -x + +# Ensure that needed directories exist +mkdir -p ~/Downloads # For downloads +mkdir -p ~/bin # Personal bin dir. Reduces the risk of breaking ~/.local/bin +mkdir -p ~/projects # For my projects +mkdir -p ~/src # For compiling other people's projects +mkdir -p ~/services # Service dir for servers mostly + +# Build the directory structure if ~/.config +mkdir -p ~/.config/nvim +mkdir -p ~/.config/termux +mkdir -p ~/.config/logid +mkdir -p ~/.config/systemd/user +mkdir -p ~/.config/git +mkdir -p ~/.config/git/config-fragments +mkdir -p ~/.config/user-tmpfiles.d +mkdir -p ~/.cargo +mkdir -p ~/.ssh + +# Build directory structure for program plugins +mkdir -p ~/.local/share/nautilus/scripts/ + +# -- Config Linking -- + +# Configure the shell +ln -sf $EWCONFIG_ROOT/configs/shells/zsh/.zshrc ~/.zshrc +ln -sf $EWCONFIG_ROOT/configs/shells/bash/.bashrc ~/.bashrc + +# Configure Git +ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig +ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers +ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap + +# Check if GIT is installed > 2.34 +set +x +if type -p git > /dev/null; then + # If GIT has SSH signing support, enable it + git_version=$(git --version | cut -d' ' -f3 | cut -d'.' -f1-2) + minimum_version=2.34 + if [ "$(printf '%s\n' "$minimum_version" "$git_version" | sort -V | head -n1)" = "$minimum_version" ]; then + set -x + ln -sf $EWCONFIG_ROOT/configs/git/config-fragments/enable-signing.gitconfig ~/.config/git/config-fragments/enable-signing.gitconfig + fi +fi + +# Configure SSH +ln -sf $EWCONFIG_ROOT/configs/ssh/config ~/.ssh/config +chmod 644 "$HOME/.ssh/config" +chown "$USER:$USER" "$HOME/.ssh/config" + +# Configure (neo)Vim +ln -sf $EWCONFIG_ROOT/configs/nvim/init.vim ~/.config/nvim/init.vim +ln -sf $EWCONFIG_ROOT/configs/nvim/pack ~/.config/nvim/pack +ln -sf $EWCONFIG_ROOT/configs/nvim/third_party ~/.config/nvim/third_party + +# Nautilus right-click scripts +ln -sf $EWCONFIG_ROOT/configs/nautilus/scripts/* ~/.local/share/nautilus/scripts/ + +# Tabset configs +ln -sf $EWCONFIG_ROOT/configs/tabset/ ~/.config/tabset + +# Rofi configs +ln -sf $EWCONFIG_ROOT/configs/rofi/ ~/.config/rofi + +# Cargo +ln -sf $EWCONFIG_ROOT/configs/cargo/config.toml ~/.cargo/config.toml + +# Termux +ln -sf $EWCONFIG_ROOT/configs/termux/termux.properties ~/.config/termux/termux.properties + +# Set up user-tempfiles configs +ln -sf $EWCONFIG_ROOT/configs/user-tmpfiles.d/* ~/.config/user-tmpfiles.d/ + +# Logid config +ln -sf $EWCONFIG_ROOT/configs/logid/logid.cfg ~/.config/logid/logid.cfg + +# -- Optional Configs -- +set +x + +# If ~/.config/git/config-fragments/personal-info.gitconfig does not exist +if [ ! -f ~/.config/git/config-fragments/personal-info.gitconfig ]; then + # Ask if the user wants to install personal GIT config + echo "Do you want to install the personal GIT config? (y/n)" + read -r install_git_config + if [ "$install_git_config" = "y" ]; then + ln -sf $EWCONFIG_ROOT/configs/git/config-fragments/personal-info.gitconfig ~/.config/git/config-fragments/personal-info.gitconfig + fi +fi + +# Link houdini scripts for appropriate versions +if [ -d ~/houdini19.5 ]; then mkdir -p ~/houdini19.5/scripts; ln -sf $EWCONFIG_ROOT/configs/houdini19.5/scripts/* ~/houdini19.5/scripts; fi + +# Link blender scripts for appropriate versions +if [ -d ~/.config/blender/3.6 ]; then ln -sf $EWCONFIG_ROOT/configs/blender/3.x/scripts/addons/* ~/.config/blender/3.6/scripts/addons/; fi + +# -- Finalization -- + +# On systems that need it, configure Gnome +sh ./helpers/configure-gnome.sh + +# Attempt to force a termux settings reload on Android devices +termux-reload-settings || true diff --git a/install-windows.sh b/install-windows.sh new file mode 100644 index 0000000..e8a0b62 --- /dev/null +++ b/install-windows.sh @@ -0,0 +1,40 @@ +#! /bin/sh +set -e +export EWCONFIG_ROOT=$(dirname $(readlink -f $0)) + +# Pull git submodules if needed +echo "Syncing git submodules..." +git submodule update --init --recursive + +# Make sure scripts are all executable +chmod +x $EWCONFIG_ROOT/configs/scripts/* +chmod +x $EWCONFIG_ROOT/configs/nautilus/scripts/* + +# -- Directory Setup -- +set -x + +# Ensure that needed directories exist +mkdir -p ~/bin # Personal bin dir. Reduces the risk of breaking ~/.local/bin +mkdir -p ~/projects # For my projects + +# Build the directory structure if ~/.config +mkdir -p ~/.config/git +mkdir -p ~/.config/git/config-fragments +mkdir -p ~/.cargo +mkdir -p ~/.ssh + +# -- Config Linking -- + +# Configure the shell +ln -sf $EWCONFIG_ROOT/configs/shells/zsh/.zshrc ~/.zshrc +ln -sf $EWCONFIG_ROOT/configs/shells/bash/.bashrc ~/.bashrc + +# Configure Git +ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig +ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers +ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap + +# Configure SSH +ln -sf $EWCONFIG_ROOT/configs/ssh/config ~/.ssh/config +chmod 644 "$HOME/.ssh/config" +chown "$USER:$USER" "$HOME/.ssh/config" \ No newline at end of file From d5f8224786679de22ffd899565442c9a66d60c4e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:42:14 -0400 Subject: [PATCH 154/326] Dont try to pull submodules if not possible --- configs/shells/bash/macros.sh | 2 +- install-linux.sh | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 130c2c5..9d8d69d 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -164,4 +164,4 @@ ewconfig-pull() { cd ~/.config/ewconfig git pull cd $cwd -} \ No newline at end of file +} diff --git a/install-linux.sh b/install-linux.sh index 60aa757..732962c 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -6,8 +6,11 @@ export EWCONFIG_ROOT=$(dirname $(readlink -f $0)) # Pull git submodules if needed if type -p git > /dev/null; then - echo "Syncing git submodules..." - git submodule update --init --recursive + # If we have permission to run git + if [ -d "$EWCONFIG_ROOT/.git" ]; then + echo "Syncing git submodules..." + git submodule update --init --recursive + fi fi # Make sure scripts are all executable From 2fb13d0fd1e6f69eedc23395dd1430ea689db898 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:45:15 -0400 Subject: [PATCH 155/326] Ensure we have sort -v --- install-linux.sh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/install-linux.sh b/install-linux.sh index 732962c..5fcebd1 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -55,12 +55,15 @@ ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap # Check if GIT is installed > 2.34 set +x if type -p git > /dev/null; then - # If GIT has SSH signing support, enable it - git_version=$(git --version | cut -d' ' -f3 | cut -d'.' -f1-2) - minimum_version=2.34 - if [ "$(printf '%s\n' "$minimum_version" "$git_version" | sort -V | head -n1)" = "$minimum_version" ]; then - set -x - ln -sf $EWCONFIG_ROOT/configs/git/config-fragments/enable-signing.gitconfig ~/.config/git/config-fragments/enable-signing.gitconfig + # If sort has a -V option + if sort --help | grep -q -- -V; then + # If GIT has SSH signing support, enable it + git_version=$(git --version | cut -d' ' -f3 | cut -d'.' -f1-2) + minimum_version=2.34 + if [ "$(printf '%s\n' "$minimum_version" "$git_version" | sort -V | head -n1)" = "$minimum_version" ]; then + set -x + ln -sf $EWCONFIG_ROOT/configs/git/config-fragments/enable-signing.gitconfig ~/.config/git/config-fragments/enable-signing.gitconfig + fi fi fi From 2545620550844d6dd097bc4a5be5175d9dba877a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:48:07 -0400 Subject: [PATCH 156/326] Use man --- install-linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-linux.sh b/install-linux.sh index 5fcebd1..b6c6d8f 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -56,7 +56,7 @@ ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap set +x if type -p git > /dev/null; then # If sort has a -V option - if sort --help | grep -q -- -V; then + if man sort | grep -q -- -V; then # If GIT has SSH signing support, enable it git_version=$(git --version | cut -d' ' -f3 | cut -d'.' -f1-2) minimum_version=2.34 From d38a177aed728023a465cc7c9fb8ca968b424bff Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:49:36 -0400 Subject: [PATCH 157/326] Handle chown not existing --- install-linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-linux.sh b/install-linux.sh index b6c6d8f..1dd4fcc 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -70,7 +70,7 @@ fi # Configure SSH ln -sf $EWCONFIG_ROOT/configs/ssh/config ~/.ssh/config chmod 644 "$HOME/.ssh/config" -chown "$USER:$USER" "$HOME/.ssh/config" +if type -p chown > /dev/null; then chown "$USER:$USER" "$HOME/.ssh/config"; fi # Configure (neo)Vim ln -sf $EWCONFIG_ROOT/configs/nvim/init.vim ~/.config/nvim/init.vim From 4da10ee1e16b7f78d613dc04986dd2273f78dd4e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:55:54 -0400 Subject: [PATCH 158/326] Handle SDF things --- configs/shells/bash/macros.sh | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 9d8d69d..3d43727 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -1,4 +1,9 @@ -alias ls="ls --color=auto" +# If ls has `--color` support +if ls --color > /dev/null 2>&1; then + alias ls="ls --color=auto" +fi + +# Main aliases alias ll="ls -l" alias la="ls -a" alias :q="exit" @@ -165,3 +170,23 @@ ewconfig-pull() { git pull cd $cwd } + +# Updates the ewconfig on machines that don't have git +ewconfig-pull-zip(){ + cwd=$(pwd) + # If $EWCONFIG_ROOT/.git exists, don't let the user run this + if [ -d $EWCONFIG_ROOT/.git ]; then + echo "You can't run this command when ~/.config/ewconfig is a git repo!" + return 1 + fi + + # Download the latest zip + cd ~/Downloads + curl -L https://ewp.fyi/config.zip -o ewconfig.zip + rm -rf ~/.config/ewconfig + unzip -o ewconfig.zip -d ~/.config/ewconfig + rm ewconfig.zip + + # Return to the original directory + cd $cwd +} From ed707c48b8fffd94f73627544be397634412fcfe Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 10:57:23 -0400 Subject: [PATCH 159/326] Fix bug --- configs/shells/bash/macros.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 3d43727..46160f1 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -184,7 +184,8 @@ ewconfig-pull-zip(){ cd ~/Downloads curl -L https://ewp.fyi/config.zip -o ewconfig.zip rm -rf ~/.config/ewconfig - unzip -o ewconfig.zip -d ~/.config/ewconfig + unzip ewconfig.zip + mv ewconfig-master ~/.config/ewconfig rm ewconfig.zip # Return to the original directory From 26519c8b862bde851dd6ef74a1ea77a4448f9e31 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:07:31 -0400 Subject: [PATCH 160/326] Add BSD support to info.sh --- configs/shells/zsh/info.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/configs/shells/zsh/info.sh b/configs/shells/zsh/info.sh index e4dcff5..ee1ad43 100644 --- a/configs/shells/zsh/info.sh +++ b/configs/shells/zsh/info.sh @@ -1,5 +1,11 @@ -echo "$fg[green]Platform:$reset_color $(uname -o) $(uname -r)" -echo "$fg[green]Uptime:$reset_color $(uptime -p)" + +# If `uname -s` is a BSD +if [ uname -s | grep BSD > /dev/null ]; then + echo "$fg[green]Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" +else # Linux + echo "$fg[green]Platform:$reset_color $(uname -o) $(uname -r)" + echo "$fg[green]Uptime:$reset_color $(uptime -p)" +fi # Determine if $EWCONFIG_ROOT contains uncommitted changes if [ -d $EWCONFIG_ROOT/.git ]; then From 8b10b3f3dbb57e3543cde52b5ff86784505b2d5d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:09:00 -0400 Subject: [PATCH 161/326] test --- configs/shells/zsh/info.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/zsh/info.sh b/configs/shells/zsh/info.sh index ee1ad43..cd753cd 100644 --- a/configs/shells/zsh/info.sh +++ b/configs/shells/zsh/info.sh @@ -1,6 +1,6 @@ # If `uname -s` is a BSD -if [ uname -s | grep BSD > /dev/null ]; then +if [ uname -s | grep BSD - > /dev/null ]; then echo "$fg[green]Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" else # Linux echo "$fg[green]Platform:$reset_color $(uname -o) $(uname -r)" From 1c93a3848eb31ccb8b0f3217378d6e9e859077f0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:10:54 -0400 Subject: [PATCH 162/326] fix --- configs/shells/zsh/info.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/zsh/info.sh b/configs/shells/zsh/info.sh index cd753cd..d17c368 100644 --- a/configs/shells/zsh/info.sh +++ b/configs/shells/zsh/info.sh @@ -1,6 +1,6 @@ # If `uname -s` is a BSD -if [ uname -s | grep BSD - > /dev/null ]; then +if [ $(uname -s | grep -c BSD) -gt 0 ]; then echo "$fg[green]Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" else # Linux echo "$fg[green]Platform:$reset_color $(uname -o) $(uname -r)" From a44556d80ea88a69d98c9c4ba354e3d9717588d0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:15:14 -0400 Subject: [PATCH 163/326] fix infinite links --- configs/nvim/pack/pack | 1 - configs/nvim/third_party/third_party | 1 - configs/rofi/rofi | 1 - configs/tabset/tabset | 1 - 4 files changed, 4 deletions(-) delete mode 120000 configs/nvim/pack/pack delete mode 120000 configs/nvim/third_party/third_party delete mode 120000 configs/rofi/rofi delete mode 120000 configs/tabset/tabset diff --git a/configs/nvim/pack/pack b/configs/nvim/pack/pack deleted file mode 120000 index 7c8b955..0000000 --- a/configs/nvim/pack/pack +++ /dev/null @@ -1 +0,0 @@ -/home/ewpratten/.config/ewconfig/configs/nvim/pack \ No newline at end of file diff --git a/configs/nvim/third_party/third_party b/configs/nvim/third_party/third_party deleted file mode 120000 index 937284f..0000000 --- a/configs/nvim/third_party/third_party +++ /dev/null @@ -1 +0,0 @@ -/home/ewpratten/.config/ewconfig/configs/nvim/third_party \ No newline at end of file diff --git a/configs/rofi/rofi b/configs/rofi/rofi deleted file mode 120000 index 7be4e32..0000000 --- a/configs/rofi/rofi +++ /dev/null @@ -1 +0,0 @@ -/home/ewpratten/.config/ewconfig/configs/rofi/ \ No newline at end of file diff --git a/configs/tabset/tabset b/configs/tabset/tabset deleted file mode 120000 index a3e8e62..0000000 --- a/configs/tabset/tabset +++ /dev/null @@ -1 +0,0 @@ -/home/ewpratten/.config/ewconfig/configs/tabset/ \ No newline at end of file From ab4d77a1264e0b1edde9d43e3f1ae4bab3d3da42 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:19:06 -0400 Subject: [PATCH 164/326] test skipping signers --- install-windows.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-windows.sh b/install-windows.sh index e8a0b62..02d4483 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -31,7 +31,7 @@ ln -sf $EWCONFIG_ROOT/configs/shells/bash/.bashrc ~/.bashrc # Configure Git ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig -ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers +ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers || true ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap # Configure SSH From bfcc543e6586e8c82fc11c9cf4888605ed32cb97 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:20:21 -0400 Subject: [PATCH 165/326] fix reload commands --- configs/shells/bash/macros.sh | 2 +- configs/shells/zsh/macros.sh | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 46160f1..0f5e54b 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -9,7 +9,7 @@ alias la="ls -a" alias :q="exit" alias :wq="exit" alias cls=clear -alias zshreload="source ~/.zshrc" +alias bashreload="source ~/.bashrc" alias wg-easykeys="wg genkey | tee >(wg pubkey)" alias nvim-tmp="nvim $(mktemp)" alias flush-dns="sudo systemd-resolve --flush-caches" diff --git a/configs/shells/zsh/macros.sh b/configs/shells/zsh/macros.sh index d043a99..22a53f6 100644 --- a/configs/shells/zsh/macros.sh +++ b/configs/shells/zsh/macros.sh @@ -1,6 +1,9 @@ # We are compatible with bash, so first load the bash-specific macros . $EWCONFIG_ROOT/configs/shells/bash/macros.sh +# Aliases +alias zshreload="source ~/.zshrc" + # Search for a process proc-grep() { if [ $# != 1 ]; then From d3cbce8c2519b57520d445915180a18b000711b8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:27:14 -0400 Subject: [PATCH 166/326] Allow bash to show info text --- configs/shells/bash/.bashrc | 3 +++ configs/shells/{zsh => bash}/info.sh | 18 ++++++++++++++---- configs/shells/zsh/.zshrc | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) rename configs/shells/{zsh => bash}/info.sh (57%) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 23bf9d4..2529451 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -4,6 +4,9 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" # Load macros . $EWCONFIG_ROOT/configs/shells/bash/macros.sh +# Show some host info +. $EWCONFIG_ROOT/configs/shells/bash/info.sh + # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" diff --git a/configs/shells/zsh/info.sh b/configs/shells/bash/info.sh similarity index 57% rename from configs/shells/zsh/info.sh rename to configs/shells/bash/info.sh index d17c368..dea0843 100644 --- a/configs/shells/zsh/info.sh +++ b/configs/shells/bash/info.sh @@ -1,16 +1,26 @@ +# Define red and green based on the shell +if [ -n "$BASH_VERSION" ]; then + red='\033[0;31m' + green='\033[0;32m' + reset_color='\033[0m' +elif [ -n "$ZSH_VERSION" ]; then + red="$fg[red]" + green="$fg[green]" +fi + # If `uname -s` is a BSD if [ $(uname -s | grep -c BSD) -gt 0 ]; then - echo "$fg[green]Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" + echo -e "${green}Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" else # Linux - echo "$fg[green]Platform:$reset_color $(uname -o) $(uname -r)" - echo "$fg[green]Uptime:$reset_color $(uptime -p)" + echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" + echo -e "${green}Uptime:$reset_color $(uptime -p)" fi # Determine if $EWCONFIG_ROOT contains uncommitted changes if [ -d $EWCONFIG_ROOT/.git ]; then if [ -n "$(git -C $EWCONFIG_ROOT status --porcelain)" ]; then - echo "$fg[red]ewconfig contains uncommitted changes$reset_color" + echo -e "${red}ewconfig contains uncommitted changes$reset_color" fi fi diff --git a/configs/shells/zsh/.zshrc b/configs/shells/zsh/.zshrc index 6df5967..8e5f39f 100644 --- a/configs/shells/zsh/.zshrc +++ b/configs/shells/zsh/.zshrc @@ -14,7 +14,7 @@ if [ -f $EWCONFIG_ROOT/configs/zsh/by_host/$HOSTNAME.sh ]; then fi # Show some host info -. $EWCONFIG_ROOT/configs/shells/zsh/info.sh +. $EWCONFIG_ROOT/configs/shells/bash/info.sh # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" From 39205aee7674f14685d76f1a4ad1530949388a60 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:32:46 -0400 Subject: [PATCH 167/326] windows-specific line --- configs/shells/bash/.bashrc | 6 +++--- configs/shells/bash/info.sh | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 2529451..9b5f2f8 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -1,12 +1,12 @@ # This is a somewhat hacky bashrc that is used to provide some of the conveniences from my zshrc on machines that I can't get zsh on export EWCONFIG_ROOT="$HOME/.config/ewconfig" -# Load macros -. $EWCONFIG_ROOT/configs/shells/bash/macros.sh - # Show some host info . $EWCONFIG_ROOT/configs/shells/bash/info.sh +# Load macros +. $EWCONFIG_ROOT/configs/shells/bash/macros.sh + # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" diff --git a/configs/shells/bash/info.sh b/configs/shells/bash/info.sh index dea0843..dc63aa5 100644 --- a/configs/shells/bash/info.sh +++ b/configs/shells/bash/info.sh @@ -9,10 +9,14 @@ elif [ -n "$ZSH_VERSION" ]; then green="$fg[green]" fi -# If `uname -s` is a BSD -if [ $(uname -s | grep -c BSD) -gt 0 ]; then +# Different OSes have different ways of displaying info +if [ $(uname -s | grep -c BSD) -gt 0 ]; then # BSD echo -e "${green}Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" -else # Linux + +elif [ $(uname -s | grep -c Msys) -gt 0 ]; then # Windows + echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" + +else # Linux-y things echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" echo -e "${green}Uptime:$reset_color $(uptime -p)" fi From 977025272c4b3fdcebaa6185b890eb67e42475c4 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:33:46 -0400 Subject: [PATCH 168/326] debug --- configs/shells/bash/.bashrc | 2 ++ configs/shells/bash/info.sh | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 9b5f2f8..c0850d3 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -2,9 +2,11 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" # Show some host info +echo "info" . $EWCONFIG_ROOT/configs/shells/bash/info.sh # Load macros +echo "macros" . $EWCONFIG_ROOT/configs/shells/bash/macros.sh # I always want my ~/bin to be in my PATH diff --git a/configs/shells/bash/info.sh b/configs/shells/bash/info.sh index dc63aa5..86061c1 100644 --- a/configs/shells/bash/info.sh +++ b/configs/shells/bash/info.sh @@ -1,4 +1,5 @@ +echo "in info" # Define red and green based on the shell if [ -n "$BASH_VERSION" ]; then red='\033[0;31m' @@ -15,7 +16,7 @@ if [ $(uname -s | grep -c BSD) -gt 0 ]; then # BSD elif [ $(uname -s | grep -c Msys) -gt 0 ]; then # Windows echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" - + else # Linux-y things echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" echo -e "${green}Uptime:$reset_color $(uptime -p)" From 4558ea4b68a347b4f60080249c4aba47fcc0911d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:36:35 -0400 Subject: [PATCH 169/326] undo --- configs/shells/bash/.bashrc | 2 -- configs/shells/bash/info.sh | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index c0850d3..9b5f2f8 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -2,11 +2,9 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" # Show some host info -echo "info" . $EWCONFIG_ROOT/configs/shells/bash/info.sh # Load macros -echo "macros" . $EWCONFIG_ROOT/configs/shells/bash/macros.sh # I always want my ~/bin to be in my PATH diff --git a/configs/shells/bash/info.sh b/configs/shells/bash/info.sh index 86061c1..dc63aa5 100644 --- a/configs/shells/bash/info.sh +++ b/configs/shells/bash/info.sh @@ -1,5 +1,4 @@ -echo "in info" # Define red and green based on the shell if [ -n "$BASH_VERSION" ]; then red='\033[0;31m' @@ -16,7 +15,7 @@ if [ $(uname -s | grep -c BSD) -gt 0 ]; then # BSD elif [ $(uname -s | grep -c Msys) -gt 0 ]; then # Windows echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" - + else # Linux-y things echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" echo -e "${green}Uptime:$reset_color $(uptime -p)" From a8c510a793f0f2b9ab40897d0186f406aa4d68ec Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:48:59 -0400 Subject: [PATCH 170/326] Support windows terminal --- configs/windows-terminal/settings.json | 74 ++++++++++++++++++++++++++ install-windows.sh | 1 + 2 files changed, 75 insertions(+) create mode 100644 configs/windows-terminal/settings.json diff --git a/configs/windows-terminal/settings.json b/configs/windows-terminal/settings.json new file mode 100644 index 0000000..52b26ee --- /dev/null +++ b/configs/windows-terminal/settings.json @@ -0,0 +1,74 @@ +{ + "$help": "https://aka.ms/terminal-documentation", + "$schema": "https://aka.ms/terminal-profiles-schema", + "actions": [ + { + "command": { + "action": "copy", + "singleLine": false + }, + "keys": "ctrl+shift+c" + }, + { + "command": "paste", + "keys": "ctrl+shift+v" + } + ], + "copyFormatting": "none", + "copyOnSelect": false, + "defaultProfile": "{2ece5bfe-50ed-5f3a-ab87-5cd4baafed2b}", + "newTabMenu": [ + { + "type": "remainingProfiles" + } + ], + "profiles": { + "defaults": { + "useAtlasEngine": true + }, + "list": [ + { + "commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + "font": { + "face": "Consolas" + }, + "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", + "hidden": false, + "name": "Windows PowerShell" + }, + { + "commandline": "%SystemRoot%\\System32\\cmd.exe", + "font": { + "face": "Consolas" + }, + "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", + "hidden": false, + "name": "Command Prompt" + }, + { + "font": { + "face": "Consolas" + }, + "guid": "{2ece5bfe-50ed-5f3a-ab87-5cd4baafed2b}", + "commandline": "C:/Program Files/Git/bin/bash.exe --login", + "hidden": false, + "name": "Git Bash", + "source": "Git" + }, + { + "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}", + "hidden": true, + "name": "Ubuntu", + "source": "Windows.Terminal.Wsl" + }, + { + "guid": "{51855cb2-8cce-5362-8f54-464b92b32386}", + "hidden": false, + "name": "Ubuntu", + "source": "CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc" + } + ] + }, + "schemes": [], + "themes": [] +} \ No newline at end of file diff --git a/install-windows.sh b/install-windows.sh index 02d4483..a8c68ae 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -28,6 +28,7 @@ mkdir -p ~/.ssh # Configure the shell ln -sf $EWCONFIG_ROOT/configs/shells/zsh/.zshrc ~/.zshrc ln -sf $EWCONFIG_ROOT/configs/shells/bash/.bashrc ~/.bashrc +ln -sf $EWCONFIG_ROOT/configs/windows-terminal/settings.json $LOCALAPPDATA/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json # Configure Git ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig From 70100b7f8babf6814da50b180e3cdbeb3aabe4ac Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 11:50:39 -0400 Subject: [PATCH 171/326] cleanup --- configs/windows-terminal/settings.json | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/configs/windows-terminal/settings.json b/configs/windows-terminal/settings.json index 52b26ee..17841ce 100644 --- a/configs/windows-terminal/settings.json +++ b/configs/windows-terminal/settings.json @@ -29,40 +29,46 @@ "list": [ { "commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", "font": { "face": "Consolas" }, - "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", "hidden": false, "name": "Windows PowerShell" }, { "commandline": "%SystemRoot%\\System32\\cmd.exe", + "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", "font": { "face": "Consolas" }, - "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", "hidden": false, "name": "Command Prompt" }, { + "guid": "{2ece5bfe-50ed-5f3a-ab87-5cd4baafed2b}", + "commandline": "C:/Program Files/Git/bin/bash.exe --login", "font": { "face": "Consolas" }, - "guid": "{2ece5bfe-50ed-5f3a-ab87-5cd4baafed2b}", - "commandline": "C:/Program Files/Git/bin/bash.exe --login", "hidden": false, "name": "Git Bash", "source": "Git" }, { "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}", + "font": { + "face": "Consolas" + }, "hidden": true, "name": "Ubuntu", "source": "Windows.Terminal.Wsl" }, { "guid": "{51855cb2-8cce-5362-8f54-464b92b32386}", + "font": { + "face": "Consolas" + }, "hidden": false, "name": "Ubuntu", "source": "CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc" From 87fb569719d5e0daadb70970fedb79363529d7ed Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:04:57 -0400 Subject: [PATCH 172/326] better mailmap handling --- configs/git/.gitconfig | 5 ++--- .../git/config-fragments/global-mailmap.gitconfig | 4 ++++ install-linux.sh | 13 +++++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 configs/git/config-fragments/global-mailmap.gitconfig diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index e113bf8..c5d7a84 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -2,6 +2,7 @@ # NOTE: These paths are imported if they exist and ignored if they don't # This allows us to have a single config file for all our machines # and control the specifics by symlinking the relevant files per-machine + path = ~/.config/git/config-fragments/global-mailmap.gitconfig path = ~/.config/git/config-fragments/personal-info.gitconfig path = ~/.config/git/config-fragments/enable-signing.gitconfig @@ -20,6 +21,7 @@ --pretty=format:'%C(yellow)commit %h%C(auto)%d%n%C(cyan)Author:%Creset %aN %C(dim white)<%aE>%n%C(cyan)Date:%Creset %C(dim white)%ad (%ar)%n%s%n' \ --date=format:'%b %d %Y %H:%M:%S %z' branches = branch -a -l -vv + overview = log --all --pretty=format:'%C(green)commit %C(yellow)%h%C(green) by %C(reset)%C(yellow)%aN %C(dim white)(%ar) %n%C(dim white)%S%n%B%n' [filter "lfs"] clean = git-lfs clean -- %f @@ -37,6 +39,3 @@ [credential "https://gist.github.com"] helper = helper = !/usr/bin/gh auth git-credential - -[mailmap] - file = ~/.config/git/.mailmap diff --git a/configs/git/config-fragments/global-mailmap.gitconfig b/configs/git/config-fragments/global-mailmap.gitconfig new file mode 100644 index 0000000..4953fee --- /dev/null +++ b/configs/git/config-fragments/global-mailmap.gitconfig @@ -0,0 +1,4 @@ +# Feel free to overwrite this file. It is only copied once. + +[mailmap] + file = ~/.config/git/.mailmap diff --git a/install-linux.sh b/install-linux.sh index 1dd4fcc..b52025a 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -52,6 +52,11 @@ ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap +# Copy the global mailmap file once +if [ ! -f ~/.config/git/config-fragments/global-mailmap.gitconfig ]; then + cp $EWCONFIG_ROOT/configs/git/config-fragments/global-mailmap.gitconfig ~/.config/git/config-fragments/global-mailmap.gitconfig +fi + # Check if GIT is installed > 2.34 set +x if type -p git > /dev/null; then @@ -74,17 +79,17 @@ if type -p chown > /dev/null; then chown "$USER:$USER" "$HOME/.ssh/config"; fi # Configure (neo)Vim ln -sf $EWCONFIG_ROOT/configs/nvim/init.vim ~/.config/nvim/init.vim -ln -sf $EWCONFIG_ROOT/configs/nvim/pack ~/.config/nvim/pack -ln -sf $EWCONFIG_ROOT/configs/nvim/third_party ~/.config/nvim/third_party +unlink ~/.config/nvim/pack || true; ln -sf $EWCONFIG_ROOT/configs/nvim/pack ~/.config/nvim/pack +unlink ~/.config/nvim/third_party || true; ln -sf $EWCONFIG_ROOT/configs/nvim/third_party ~/.config/nvim/third_party # Nautilus right-click scripts ln -sf $EWCONFIG_ROOT/configs/nautilus/scripts/* ~/.local/share/nautilus/scripts/ # Tabset configs -ln -sf $EWCONFIG_ROOT/configs/tabset/ ~/.config/tabset +unlink ~/.config/tabset || true; ln -sf $EWCONFIG_ROOT/configs/tabset ~/.config/tabset # Rofi configs -ln -sf $EWCONFIG_ROOT/configs/rofi/ ~/.config/rofi +unlink ~/.config/rofi || true; ln -sf $EWCONFIG_ROOT/configs/rofi ~/.config/rofi # Cargo ln -sf $EWCONFIG_ROOT/configs/cargo/config.toml ~/.cargo/config.toml From 44c8767c77144e5953dcd57137b7c2778a241f03 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:06:34 -0400 Subject: [PATCH 173/326] do mailmap on win --- install-windows.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/install-windows.sh b/install-windows.sh index a8c68ae..3dcff82 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -35,6 +35,11 @@ ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers || true ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap +# Copy the global mailmap file once +if [ ! -f ~/.config/git/config-fragments/global-mailmap.gitconfig ]; then + cp $EWCONFIG_ROOT/configs/git/config-fragments/global-mailmap.gitconfig ~/.config/git/config-fragments/global-mailmap.gitconfig +fi + # Configure SSH ln -sf $EWCONFIG_ROOT/configs/ssh/config ~/.ssh/config chmod 644 "$HOME/.ssh/config" From f1944e37d85718795450bbf4577ba196ea3d0c84 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:29:13 -0400 Subject: [PATCH 174/326] Add a script for multirepo author stats --- configs/scripts/git-authors-multirepo | 60 +++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100755 configs/scripts/git-authors-multirepo diff --git a/configs/scripts/git-authors-multirepo b/configs/scripts/git-authors-multirepo new file mode 100755 index 0000000..648bada --- /dev/null +++ b/configs/scripts/git-authors-multirepo @@ -0,0 +1,60 @@ +#! /usr/bin/env python3 +import subprocess +import argparse +import sys +from pathlib import Path + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + description="git authors, but for multiple repos at once" + ) + ap.add_argument( + "walk_start_dir", + help="Directory to start walking from", + default=Path("."), + type=Path, + ) + args = ap.parse_args() + + # Find every subdirectory that is a git repo + git_dirs = [] + for path in args.walk_start_dir.iterdir(): + if path.is_dir() and (path / ".git").is_dir(): + git_dirs.append(path) + + # Collect the results of `git authors` from each repo + authors = [] + for git_dir in git_dirs: + output = subprocess.check_output(["git", "authors"], cwd=git_dir) + lines = output.split(b"\n") + for line in lines: + try: + line = line.decode("utf-8") + except UnicodeDecodeError: + continue + if line and len(line.split("\t")) >1: + commits, author = line.split("\t", 1) + authors.append((int(commits.strip()), author)) + + # Combine the results + combined = {} + for author in authors: + if author[1] not in combined: + combined[author[1]] = 0 + combined[author[1]] += author[0] + + # Convert back to a list + authors = [(combined[author], author) for author in combined] + authors.sort(reverse=True) + + # Print + for author in authors: + print(f"{author[0]}\t{author[1]}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From f1434058693321b3bb18c45d574bfa9339041bf3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:32:28 -0400 Subject: [PATCH 175/326] studio python --- configs/shells/bash/.bashrc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 9b5f2f8..8669788 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -14,3 +14,6 @@ export PATH="$HOME/.local/bin:$PATH" # A basic prompt to display user@host dir sign export PS1="(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" + +# If found, load studio python +[[ -d "/c/Programs/software/win/core/python/python_3.7.7" ]] && export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH" From 1d05d201e5fd7931144fe437eb7cab03f996cefd Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:33:48 -0400 Subject: [PATCH 176/326] fix uname flag --- configs/shells/bash/info.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/bash/info.sh b/configs/shells/bash/info.sh index dc63aa5..b029333 100644 --- a/configs/shells/bash/info.sh +++ b/configs/shells/bash/info.sh @@ -13,7 +13,7 @@ fi if [ $(uname -s | grep -c BSD) -gt 0 ]; then # BSD echo -e "${green}Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" -elif [ $(uname -s | grep -c Msys) -gt 0 ]; then # Windows +elif [ $(uname -o | grep -c Msys) -gt 0 ]; then # Windows echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" else # Linux-y things From e469e4343ff46a0dc8ae55d7c11c72532f1d1985 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:37:46 -0400 Subject: [PATCH 177/326] fix py paths --- configs/scripts/git-authors-multirepo | 2 +- configs/shells/bash/.bashrc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/scripts/git-authors-multirepo b/configs/scripts/git-authors-multirepo index 648bada..e2ef19f 100755 --- a/configs/scripts/git-authors-multirepo +++ b/configs/scripts/git-authors-multirepo @@ -1,4 +1,4 @@ -#! /usr/bin/env python3 +#! /usr/bin/env python import subprocess import argparse import sys diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 8669788..5b43631 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -16,4 +16,4 @@ export PATH="$HOME/.local/bin:$PATH" export PS1="(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" # If found, load studio python -[[ -d "/c/Programs/software/win/core/python/python_3.7.7" ]] && export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH" +if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH"; fi From d71f354f07fc3b97993961237c50043dc9b0724c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:40:43 -0400 Subject: [PATCH 178/326] debug flag --- configs/scripts/git-authors-multirepo | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/configs/scripts/git-authors-multirepo b/configs/scripts/git-authors-multirepo index e2ef19f..1af5be8 100755 --- a/configs/scripts/git-authors-multirepo +++ b/configs/scripts/git-authors-multirepo @@ -11,18 +11,21 @@ def main() -> int: description="git authors, but for multiple repos at once" ) ap.add_argument( - "walk_start_dir", + "--start", help="Directory to start walking from", default=Path("."), type=Path, ) + ap.add_argument("--log-repos", help="Log the repos found", action="store_true") args = ap.parse_args() # Find every subdirectory that is a git repo git_dirs = [] - for path in args.walk_start_dir.iterdir(): + for path in args.start.iterdir(): if path.is_dir() and (path / ".git").is_dir(): git_dirs.append(path) + if args.log_repos: + print(f"Reading GIT repo at: {path}") # Collect the results of `git authors` from each repo authors = [] From 3cff80327292b59b8102f077a64053b8e87a4f21 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:42:06 -0400 Subject: [PATCH 179/326] recursive --- configs/scripts/git-authors-multirepo | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/scripts/git-authors-multirepo b/configs/scripts/git-authors-multirepo index 1af5be8..cbed865 100755 --- a/configs/scripts/git-authors-multirepo +++ b/configs/scripts/git-authors-multirepo @@ -21,7 +21,8 @@ def main() -> int: # Find every subdirectory that is a git repo git_dirs = [] - for path in args.start.iterdir(): + all_dirs_recursive = list(args.start.glob("**/*")) + for path in all_dirs_recursive: if path.is_dir() and (path / ".git").is_dir(): git_dirs.append(path) if args.log_repos: From c6fafed3dea0ecad4e35beabc6b9bd0048ee8d6e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 19 Oct 2023 14:46:12 -0400 Subject: [PATCH 180/326] fix glob --- configs/scripts/git-authors-multirepo | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/configs/scripts/git-authors-multirepo b/configs/scripts/git-authors-multirepo index cbed865..88f6866 100755 --- a/configs/scripts/git-authors-multirepo +++ b/configs/scripts/git-authors-multirepo @@ -21,12 +21,11 @@ def main() -> int: # Find every subdirectory that is a git repo git_dirs = [] - all_dirs_recursive = list(args.start.glob("**/*")) + all_dirs_recursive = list(args.start.glob("**/*.git")) for path in all_dirs_recursive: - if path.is_dir() and (path / ".git").is_dir(): - git_dirs.append(path) - if args.log_repos: - print(f"Reading GIT repo at: {path}") + git_dirs.append(path.parent) + if args.log_repos: + print(f"Reading GIT repo at: {path.parent}") # Collect the results of `git authors` from each repo authors = [] From faba6cb9dc771e1712567b593a96f4917643166c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 20 Oct 2023 13:00:18 -0400 Subject: [PATCH 181/326] html out --- configs/scripts/wg-handshakes | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/configs/scripts/wg-handshakes b/configs/scripts/wg-handshakes index dc8a574..74528dc 100755 --- a/configs/scripts/wg-handshakes +++ b/configs/scripts/wg-handshakes @@ -65,6 +65,12 @@ def main() -> int: ap.add_argument( "--dns-server", "-d", help="Override the DNS server to use for RDNS lookups" ) + ap.add_argument( + "--format", + default="text", + choices=["text", "html"], + help="The format to output", + ) args = ap.parse_args() # Get the output of wg show @@ -112,8 +118,18 @@ def main() -> int: outputs.sort(key=lambda x: x[1], reverse=True) # Print the outputs - for output in outputs: - print(f"{output[0]}: {output[2]}") + if args.format == "text": + for output in outputs: + print(f"{output[0]}: {output[2]}") + elif args.format == "html": + print("WireGuard Handshakes") + print("") + print("") + print("") + for output in outputs: + print(f"") + print("
NameLast Handshake
{output[0]}{output[2]}
") + print("") return 0 From 3df045be1b28e8cf796c740c62b210466cdc1f70 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 20 Oct 2023 18:42:16 -0400 Subject: [PATCH 182/326] fix video trimmer path --- configs/nautilus/scripts/Open in Video Trimmer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/nautilus/scripts/Open in Video Trimmer b/configs/nautilus/scripts/Open in Video Trimmer index 2839891..c6846c3 100755 --- a/configs/nautilus/scripts/Open in Video Trimmer +++ b/configs/nautilus/scripts/Open in Video Trimmer @@ -1,4 +1,4 @@ #! /bin/bash set -e -python3 ~/.config/ewconfig/configs/scripts/video_trimmer.py \ No newline at end of file +python3 ~/.config/ewconfig/configs/scripts/video_trimmer \ No newline at end of file From d036999c0c41040616dcb6d29bd2eb1a9098e74a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 23 Oct 2023 09:52:37 -0400 Subject: [PATCH 183/326] Git: lscommits --- configs/git/.gitconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index c5d7a84..9e7aada 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -22,6 +22,8 @@ --date=format:'%b %d %Y %H:%M:%S %z' branches = branch -a -l -vv overview = log --all --pretty=format:'%C(green)commit %C(yellow)%h%C(green) by %C(reset)%C(yellow)%aN %C(dim white)(%ar) %n%C(dim white)%S%n%B%n' + lscommits = ! ( echo -e "Commits\tFile" && git log --pretty=format: --name-only | sed '/^$/d' | sort | uniq -c | sort -g -r ) | less + lsc = lscommits [filter "lfs"] clean = git-lfs clean -- %f From 17c846897e2de7338a6eda772fbdeb497ad96895 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 23 Oct 2023 09:52:43 -0400 Subject: [PATCH 184/326] Add reconnect option --- configs/scripts/guru-vpn | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/configs/scripts/guru-vpn b/configs/scripts/guru-vpn index b6ede10..b974c6b 100755 --- a/configs/scripts/guru-vpn +++ b/configs/scripts/guru-vpn @@ -108,17 +108,23 @@ def main() -> int: prog="guru-vpn", description="Utility for connecting to the Guru VPN" ) ap.add_argument( - "operation", choices=["connect", "disconnect"], help="Operation to perform" + "operation", + choices=["connect", "disconnect", "reconnect"], + help="Operation to perform", ) args = ap.parse_args() # Ensure we can actually get credentials from the Yubikey if not has_ykman(): - print("Could not execute `ykman`. Is it installed?", file=sys.stderr); + print("Could not execute `ykman`. Is it installed?", file=sys.stderr) return 1 # Handle subcommands - cmd_fns = {"connect": handle_connect, "disconnect": handle_disconnect} + cmd_fns = { + "connect": handle_connect, + "disconnect": handle_disconnect, + "reconnect": lambda args: handle_disconnect(args) or handle_connect(args), + } return cmd_fns[args.operation](args) From de12b264ed68ebecff878ba6e68816e074f84c48 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 23 Oct 2023 10:43:53 -0400 Subject: [PATCH 185/326] impl waypoint sync --- .../Multiplayer_mc.sdf.org/config.txt | 13 ++ .../dim%0/mw$default_1.txt | 111 ++++++++++++++++++ configs/minecraft/scripts/mc_postexit.py | 50 ++++++++ configs/minecraft/scripts/mc_prelaunch.py | 31 +++++ install-linux.sh | 6 + 5 files changed, 211 insertions(+) create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt create mode 100644 configs/minecraft/scripts/mc_postexit.py create mode 100644 configs/minecraft/scripts/mc_prelaunch.py diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt new file mode 100644 index 0000000..bc89407 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt @@ -0,0 +1,13 @@ +//waypoints config options +usingMultiworldDetection:false +ignoreServerLevelId:false +defaultMultiworldId:mw-3,1,-4 +teleportationEnabled:true +usingDefaultTeleportCommand:false +serverTeleportCommandFormat:^col^warp add {x},{y},{z} +serverTeleportCommandRotationFormat:^col^warp add {x},{y},{z} +sortType:NONE +sortReversed:false + +//other config options +ignoreHeightmaps:false diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt new file mode 100644 index 0000000..662d898 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt @@ -0,0 +1,111 @@ +sets:gui.xaero_default:Buildings:Subway Stations +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:visibility_type:destination +# +waypoint:Iron Farm:I:-186:57:-217:8:false:0:Buildings:false:0:0:false +waypoint:Spawn Inn:S:-136:70:-233:8:false:0:Buildings:false:0:0:false +waypoint:Kenny Rogers Roaster:K:-156:70:-233:8:false:0:Buildings:false:0:0:false +waypoint:ITC:I:-159:70:-223:8:false:0:Buildings:false:0:0:false +waypoint:Dojo St Cafe:D:-239:67:-193:8:false:0:Buildings:false:0:0:false +waypoint:Jacob's Residence:J:-221:69:-220:8:false:0:Buildings:false:0:0:false +waypoint:Dojo St Subway Station:D:-235:69:-232:8:false:0:Buildings:false:0:0:false +waypoint:Schwa Corp HQ:S:-238:71:-254:8:false:0:Buildings:false:0:0:false +waypoint:Northern & Bee Station:S:-252:56:-433:8:false:0:Subway Stations:false:0:0:false +waypoint:Monument Place Station:S:-220:95:-186:12:false:0:Subway Stations:false:0:0:false +waypoint:[ZOG] Zombie Grinder Station:S:-236:3:-181:14:false:0:Subway Stations:false:0:0:false +waypoint:[PMI] Prismarine Inn Station:S:-204:63:578:5:false:0:Subway Stations:false:0:0:false +waypoint:[DSW] Dismal Swamp Station:S:-322:63:364:5:false:0:Subway Stations:false:0:0:false +waypoint:[APY] Apiary Station:S:-322:63:41:5:false:0:Subway Stations:false:0:0:false +waypoint:[APY] Apiary Station:S:-316:60:43:15:false:0:Subway Stations:false:0:0:false +waypoint:Southwest Blvd:S:-270:64:5:15:false:0:Subway Stations:false:0:0:false +waypoint:Southlands:S:-263:64:-45:15:false:0:Subway Stations:false:0:0:false +waypoint:Three Sisters:S:-263:64:-85:15:false:0:Subway Stations:false:0:0:false +waypoint:Small Hall Station:S:-268:65:-127:15:false:0:Subway Stations:false:0:0:false +waypoint:Monument Place Station:S:-256:65:-151:15:false:0:Subway Stations:false:0:0:false +waypoint:Zombie Grinder Station:S:-256:65:-180:15:false:0:Subway Stations:false:0:0:false +waypoint:DOJO St Station:S:-242:69:-227:15:false:0:Subway Stations:false:0:0:false +waypoint:New Cornick House Station:S:-202:66:-229:15:false:0:Subway Stations:false:0:0:false +waypoint:Wintergarden Station:S:-184:62:-243:15:false:0:Subway Stations:false:0:0:false +waypoint:[PRU] Pine Ruins Station:S:225:38:-293:15:false:0:Subway Stations:false:0:0:false +waypoint:[CSD] Canalside Station:S:143:38:-291:15:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Central Station:S:-213:42:-264:15:false:0:Subway Stations:false:0:0:false +waypoint:[SWL] Southwest Landing Station:S:-510:63:137:13:false:0:Subway Stations:false:0:0:false +waypoint:[APY] Apiary Station:S:-326:63:41:13:false:0:Subway Stations:false:0:0:false +waypoint:[ZOG] Zombie Grinder Station:S:-229:3:-181:13:false:0:Subway Stations:false:0:0:false +waypoint:[WCP] Whitecaps Station:S:-27:83:63:13:false:0:Subway Stations:false:0:0:false +waypoint:[MTV] Mountain Village Station:S:-27:38:7:13:false:0:Subway Stations:false:0:0:false +waypoint:[ESJ] Eastside Transfer:S:-31:38:-237:13:false:0:Subway Stations:false:0:0:false +waypoint:[SOU] Southlands Terminal:S:-245:42:-49:14:false:0:Subway Stations:false:0:0:false +waypoint:Monument Place Station:S:-218:43:-137:14:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Central Station:S:-213:42:-252:14:false:0:Subway Stations:false:0:0:false +waypoint:Mountain Station:S:-899:111:-607:12:false:0:Subway Stations:false:0:0:false +waypoint:Mensa Club Station:S:-900:111:-4187:12:false:0:Subway Stations:false:0:0:false +waypoint:Un-Named Interchange:I:-900:109:-2320:12:false:0:Subway Stations:false:0:0:false +waypoint:Farmington Station:S:-1630:107:-2316:12:false:0:Subway Stations:false:0:0:false +waypoint:Village Layover Station:S:-2143:97:-2315:12:false:0:Subway Stations:false:0:0:false +waypoint:Twin Peaks Station:S:-2135:97:-1015:12:false:0:Subway Stations:false:0:0:false +waypoint:Witchy Swamp Station:S:-2143:97:-1523:12:false:0:Subway Stations:false:0:0:false +waypoint:Ocean Overlook Station:S:-2726:106:-186:12:false:0:Subway Stations:false:0:0:false +waypoint:Un-Named Interchange:I:-2111:106:-186:8:false:0:Subway Stations:false:0:0:false +waypoint:End Portal Station:S:927:97:1223:12:false:0:Subway Stations:false:0:1:false +waypoint:Craniumslows Station:S:-1048:97:-94:12:false:0:Subway Stations:false:0:0:false +waypoint:Un-Named Interchange:I:-1048:97:-186:12:false:0:Subway Stations:false:0:0:false +waypoint:Un-Named Interchange:I:-1375:97:-188:12:false:0:Subway Stations:false:0:0:false +waypoint:Sheep Station:S:-1372:97:507:12:false:0:Subway Stations:false:0:0:false +waypoint:Cow Station:S:-1372:97:659:12:false:0:Subway Stations:false:0:0:false +waypoint:Un-Named Interchange:I:-1033:98:1087:12:false:0:Subway Stations:false:0:0:false +waypoint:South Station:S:-1372:98:1088:12:false:0:Subway Stations:false:0:0:false +waypoint:1567 Station:S:-1568:97:909:12:false:0:Subway Stations:false:0:0:false +waypoint:Magenta Station:S:-1372:97:908:12:false:0:Subway Stations:false:0:0:false +waypoint:Un-Named Interchange:I:-980:97:907:12:false:0:Subway Stations:false:0:0:false +waypoint:Un-Named Interchange:I:-891:95:-187:12:false:0:Subway Stations:false:0:0:false +waypoint:Dark Oak Station:S:-700:97:-185:12:false:0:Subway Stations:false:0:0:false +waypoint:Cat Ave Station:S:-536:96:-187:12:false:0:Subway Stations:false:0:0:false +waypoint:End of Line:S:-220:97:1176:12:false:0:Subway Stations:false:0:0:false +waypoint:Unknown Station:S:-220:97:6:12:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Glider Port Station:S:-219:97:-254:12:false:0:Subway Stations:false:0:0:false +waypoint:Bell Bridge / Changa Station:S:-219:97:-375:12:false:0:Subway Stations:false:0:0:false +waypoint:Eccentric Genius Station:S:-219:96:-481:12:false:0:Subway Stations:false:0:0:false +waypoint:Xiled Station:S:-219:97:-552:12:false:0:Subway Stations:false:0:0:false +waypoint:Nopantsistan Station:S:-219:98:-650:12:false:0:Subway Stations:false:0:0:false +waypoint:[HLV] Highland Village Station:S:-220:97:-1797:12:false:0:Subway Stations:false:0:0:false +waypoint:[MSW] Mid-Swamp Station:S:-187:41:-1254:14:false:0:Subway Stations:false:0:0:false +waypoint:[JOT] Jotaku Station:S:-187:42:-782:14:false:0:Subway Stations:false:0:0:false +waypoint:[NSX] Northside Transfer Station:S:-197:42:-719:5:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Central Station:S:-217:56:-275:6:false:0:Subway Stations:false:0:0:false +waypoint:[NRV] North River Station:S:-245:38:-366:5:false:0:Subway Stations:false:0:0:false +waypoint:[CMK] Central Market Station:S:-245:38:-258:5:false:0:Subway Stations:false:0:0:false +waypoint:Monument Place Station:S:-219:35:-137:13:false:0:Subway Stations:false:0:0:false +waypoint:Monument Place Station:S:-220:43:-137:10:false:0:Subway Stations:false:0:0:false +waypoint:Survey Hall Station:S:-120:59:-481:10:false:0:Subway Stations:false:0:0:false +waypoint:Inventory Station:S:-143:43:-304:10:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Square Station:S:-115:53:-256:10:false:0:Subway Stations:false:0:0:false +waypoint:Tek Square Station:S:63:65:-215:9:false:0:Subway Stations:false:0:0:false +waypoint:Manor Ave Station:S:-36:58:-225:9:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Square Station:S:-141:58:-225:9:false:0:Subway Stations:false:0:0:false +waypoint:DOJO St Station:S:-221:56:-226:9:false:0:Subway Stations:false:0:0:false +waypoint:Mob St Station:S:-389:64:-222:9:false:0:Subway Stations:false:0:0:false +waypoint:[CAT] Cat Ave Station:S:-491:64:-222:9:false:0:Subway Stations:false:0:0:false +waypoint:Garfield Station:S:-624:73:310:9:false:0:Subway Stations:false:0:0:false +waypoint:Castle Square Station:S:-616:61:-222:9:false:0:Subway Stations:false:0:0:false +waypoint:[CHA] Changa Station:S:-187:42:-373:14:false:0:Subway Stations:false:0:0:false +waypoint:[ECG] Eccentric Genius:S:-187:42:-477:14:false:0:Subway Stations:false:0:0:false +waypoint:[XIL] Xiled Station:S:-187:42:-575:14:false:0:Subway Stations:false:0:0:false +waypoint:[NOP] Nopantsistan Station:S:-187:42:-662:14:false:0:Subway Stations:false:0:0:false +waypoint:[NSX] Northside Transfer:S:-187:42:-720:14:false:0:Subway Stations:false:0:0:false +waypoint:[NPN] Nopantsistan Station:S:-245:38:-665:5:false:0:Subway Stations:false:0:0:false +waypoint:[LAY] Laydros Station:S:-245:38:-543:5:false:0:Subway Stations:false:0:0:false +waypoint:Red Station:S:-900:109:-1992:8:false:0:Subway Stations:false:0:0:false +waypoint:[NSC] North Shore City Terminal:S:-72:42:-1946:14:false:0:Subway Stations:false:0:0:false +waypoint:[NSJ] North Shore Junction:J:-183:39:-1949:8:false:0:Subway Stations:false:0:0:false +waypoint:[HLV] Highland Village Station:S:-187:41:-1736:14:false:0:Subway Stations:false:0:0:false +waypoint:[NDK] North Docks Station:S:-187:41:-1519:14:false:0:Subway Stations:false:0:0:false +waypoint:[BOH] Boathouse Station:S:-187:42:-839:14:false:0:Subway Stations:false:0:0:false +waypoint:[RST] Riverside Station:S:-189:42:-321:14:false:0:Subway Stations:false:0:0:false +waypoint:Spawn Central Station:S:-213:42:-258:13:false:0:Subway Stations:false:0:0:false +waypoint:New Base:N:-532:73:-2308:4:false:0:gui.xaero_default:false:0:1:false +waypoint:Percy Home:X:-131:66:-102:9:false:0:gui.xaero_default:false:0:1:false +waypoint:End Portal:E:921:23:1221:5:false:0:gui.xaero_default:false:0:0:false +waypoint:Miwu Home:M:-287:77:-432:9:false:0:gui.xaero_default:false:0:1:false +waypoint:Home:H:-198:69:-303:9:false:0:gui.xaero_default:false:0:1:false +waypoint:Spawn:*:-137:70:-256:0:false:0:gui.xaero_default:false:0:1:false diff --git a/configs/minecraft/scripts/mc_postexit.py b/configs/minecraft/scripts/mc_postexit.py new file mode 100644 index 0000000..1b5eb08 --- /dev/null +++ b/configs/minecraft/scripts/mc_postexit.py @@ -0,0 +1,50 @@ +#! /usr/bin/env python +import argparse +import sys +import os +import shutil +from pathlib import Path + +MINECRAFT_DIR = Path(os.environ["INST_MC_DIR"]) +WAYPOINT_BASE_DIR = MINECRAFT_DIR / "XaeroWaypoints" +GLOBAL_WAYPOINT_DIR = ( + Path(os.path.expanduser("~")) / ".config" / "minecraft" / "XaeroWaypoints" +) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(description="Post-exit tasks for Minecraft") + args = ap.parse_args() + print("[EWCONFIG] Executing post-exit tasks for Minecraft") + print(f"[EWCONFIG] Minecraft directory: {MINECRAFT_DIR}") + + # If the waypoint base dir doesn't exist, we don't need to do anything + if not WAYPOINT_BASE_DIR.exists(): + print("[EWCONFIG] No waypoints to sync") + return 0 + + # Find all multiplayer waypoint dirs + multiplayer_waypoints = [ + directory + for directory in WAYPOINT_BASE_DIR.iterdir() + if directory.is_dir() and directory.name.startswith("Multiplayer") + ] + print( + f"[EWCONFIG] Found {len(multiplayer_waypoints)} multiplayer waypoint directories" + ) + + # Copy the contents of each multiplayer waypoint dir to the global storage + for waypoint_dir in multiplayer_waypoints: + dest_dir = GLOBAL_WAYPOINT_DIR / waypoint_dir.name + print(f"[EWCONFIG] Copying {waypoint_dir} to {dest_dir}") + + # Use shutil to copy the directory + dest_dir.mkdir(parents=True, exist_ok=True) + shutil.copytree(waypoint_dir, dest_dir, dirs_exist_ok=True) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/minecraft/scripts/mc_prelaunch.py b/configs/minecraft/scripts/mc_prelaunch.py new file mode 100644 index 0000000..20ed4d2 --- /dev/null +++ b/configs/minecraft/scripts/mc_prelaunch.py @@ -0,0 +1,31 @@ +#! /usr/bin/env python +import argparse +import sys +import os +import shutil +from pathlib import Path + +MINECRAFT_DIR = Path(os.environ["INST_MC_DIR"]) +WAYPOINT_BASE_DIR = MINECRAFT_DIR / "XaeroWaypoints" +GLOBAL_WAYPOINT_DIR = ( + Path(os.path.expanduser("~")) / ".config" / "minecraft" / "XaeroWaypoints" +) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(description="Pre-launch tasks for Minecraft") + args = ap.parse_args() + print("[EWCONFIG] Executing pre-launch tasks for Minecraft") + print(f"[EWCONFIG] Minecraft directory: {MINECRAFT_DIR}") + + # Copy the global waypoint dir on top of the base waypoint dir + print(f"[EWCONFIG] Copying {GLOBAL_WAYPOINT_DIR} to {WAYPOINT_BASE_DIR}") + WAYPOINT_BASE_DIR.mkdir(parents=True, exist_ok=True) + shutil.copytree(GLOBAL_WAYPOINT_DIR, WAYPOINT_BASE_DIR, dirs_exist_ok=True) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/install-linux.sh b/install-linux.sh index b52025a..da8ea02 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -103,6 +103,12 @@ ln -sf $EWCONFIG_ROOT/configs/user-tmpfiles.d/* ~/.config/user-tmpfiles.d/ # Logid config ln -sf $EWCONFIG_ROOT/configs/logid/logid.cfg ~/.config/logid/logid.cfg +# Minecraft global configs +unlink ~/.config/minecraft || true; ln -sf $EWCONFIG_ROOT/configs/minecraft ~/.config/minecraft +if [ -d ~/.var/app/org.prismlauncher.PrismLauncher ]; then + flatpak override --user --filesystem=~/.config/minecraft org.prismlauncher.PrismLauncher +fi + # -- Optional Configs -- set +x From 0be3d1464fe1185658ef224e5a3d486f1751f0d5 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 23 Oct 2023 10:56:20 -0400 Subject: [PATCH 186/326] Load rsnmc data --- .../Multiplayer_mc.rsninja.dev/config.txt | 7 ++++ .../dim_-1/mw$default_2.txt | 17 ++++++++ .../dim_-1/mw-1,0,0_3.txt | 6 +++ .../dim_0/mw$default_1.txt | 39 +++++++++++++++++++ .../dim_0/mw$old_3.txt | 6 +++ .../dim_0/mw-4,0,2_2.txt | 4 ++ .../dim_1/mw$default_1.txt | 10 +++++ 7 files changed, 89 insertions(+) create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/config.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw$default_2.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw-1,0,0_3.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$default_1.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$old_3.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw-4,0,2_2.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_1/mw$default_1.txt diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/config.txt new file mode 100644 index 0000000..7b27802 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/config.txt @@ -0,0 +1,7 @@ +usingMultiworldDetection:true +ignoreServerLevelId:false +teleportationEnabled:true +usingDefaultTeleportCommand:true +sortType:NONE +sortReversed:false + diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw$default_2.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw$default_2.txt new file mode 100644 index 0000000..a592213 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw$default_2.txt @@ -0,0 +1,17 @@ +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:global +# +waypoint:Anarchy:A:79:128:328:13:false:0:gui.xaero_default:false:0:false +waypoint:Other roof hole:O:147:128:296:1:false:0:gui.xaero_default:false:0:false +waypoint:Carter:C:-125:128:-164:2:false:0:gui.xaero_default:false:0:false +waypoint:Percy:P:-42:132:223:10:false:0:gui.xaero_default:false:0:false +waypoint:cat:C:-51:128:536:5:false:0:gui.xaero_default:false:0:false +waypoint:Mountain Base:M:-172:131:6:2:false:0:gui.xaero_default:false:0:false +waypoint:james:J:-63:131:-64:2:false:0:gui.xaero_default:false:0:false +waypoint:Ladder to Top:L:-92:89:-30:2:false:0:gui.xaero_default:false:0:false +waypoint:te:T:6:38:251:4:false:0:gui.xaero_default:false:0:false +waypoint:ice portal:I:-650:128:-250:3:false:0:gui.xaero_default:false:0:false +waypoint:End:E:-213:131:-78:12:false:0:gui.xaero_default:false:0:false +waypoint:Home:H:-24:132:128:0:false:0:gui.xaero_default:false:0:false +waypoint:Spawn Portal:S:-74:83:2:0:false:0:gui.xaero_default:false:0:false + diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw-1,0,0_3.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw-1,0,0_3.txt new file mode 100644 index 0000000..894f424 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_-1/mw-1,0,0_3.txt @@ -0,0 +1,6 @@ +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:global +# +waypoint:jake:J:-32:131:-110:9:false:0:gui.xaero_default:false:0:false +waypoint:Home:H:-10:132:129:5:false:0:gui.xaero_default:false:0:false + diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$default_1.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$default_1.txt new file mode 100644 index 0000000..cd8155b --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$default_1.txt @@ -0,0 +1,39 @@ +sets:gui.xaero_default:RemotePlayers_Temp:Bases +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:global +# +waypoint:Anarchy:A:687:32:2547:13:false:0:gui.xaero_default:false:0:false +waypoint:Nice spot:N:257:81:319:14:false:0:gui.xaero_default:false:0:false +waypoint:Carter:C:-994:65:-1305:10:false:0:gui.xaero_default:false:0:false +waypoint:Ice portal:I:-5201:86:-1988:2:false:0:gui.xaero_default:false:0:false +waypoint:Percy:P:-327:71:1801:10:false:0:gui.xaero_default:false:0:false +waypoint:Cat's Secret Base:C:-450:64:4368:12:false:0:gui.xaero_default:false:0:false +waypoint:Squid Farm:S:1140:64:-1625:0:false:0:gui.xaero_default:false:0:false +waypoint:Chicken Farm:C:-267:55:150:0:false:0:gui.xaero_default:false:0:false +waypoint:t:T:-2391:80:1305:0:false:0:gui.xaero_default:false:0:false +waypoint:Sally:S:-1439:64:-59:10:false:0:gui.xaero_default:false:0:false +waypoint:Skeleton Farm:S:1718:70:384:0:false:0:gui.xaero_default:false:0:false +waypoint:CommonOctopus:C:1662:68:306:10:false:0:gui.xaero_default:false:0:false +waypoint:Totem farm:T:-38:71:1656:0:false:0:gui.xaero_default:false:0:false +waypoint:Wills monument:W:-1909:56:798:3:false:0:gui.xaero_default:false:0:false +waypoint:Monument:M:2799:52:1376:3:false:0:gui.xaero_default:false:0:false +waypoint:Will:W:-483:62:338:10:false:0:gui.xaero_default:false:0:false +waypoint:Tyson:T:3298:178:-2820:10:false:0:gui.xaero_default:false:0:false +waypoint:Sydney:S:-1748:110:320:10:false:0:gui.xaero_default:false:0:false +waypoint:Ethan:E:-1447:67:-830:10:false:0:gui.xaero_default:false:0:false +waypoint:Ian:I:162:105:-125:10:false:0:gui.xaero_default:false:0:false +waypoint:Cat:C:-278:70:-290:10:false:0:gui.xaero_default:false:0:false +waypoint:Turtles:T:-1761:65:40:15:false:0:gui.xaero_default:false:0:false +waypoint:Trident Farm:T:97:200:-2280:0:false:0:gui.xaero_default:false:0:false +waypoint:Test Site:T:-841:65:1421:15:false:0:gui.xaero_default:false:0:false +waypoint:Zombie Farm:Z:-475:26:1021:0:false:0:gui.xaero_default:false:0:false +waypoint:Mountain Base:M:-1304:79:-7:10:false:0:gui.xaero_default:false:0:false +waypoint:Jake:J:-435:69:-851:10:false:0:gui.xaero_default:false:0:false +waypoint:James:J:-501:66:-514:10:false:0:gui.xaero_default:false:0:false +waypoint:Nether Fortress:G:307:83:1452:6:false:0:gui.xaero_default:false:0:false +waypoint:End Portal:E:-1712:31:-622:6:false:0:gui.xaero_default:false:0:false +waypoint:Large Village:V:331:63:1396:4:false:0:gui.xaero_default:false:0:false +waypoint:Evan:H:-170:63:1038:10:false:0:gui.xaero_default:false:0:false +waypoint:Community Centre:C:-499:67:79:12:false:0:gui.xaero_default:false:0:false +waypoint:test:T:-144:68:1024:5:false:0:Bases:false:0:false + diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$old_3.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$old_3.txt new file mode 100644 index 0000000..3513847 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw$old_3.txt @@ -0,0 +1,6 @@ +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:global +# +waypoint:gui.xaero_deathpoint:D:-471:65:76:0:false:1:gui.xaero_default:false:0:true +waypoint:gui.xaero_deathpoint_old:D:-200:70:0:0:false:0:gui.xaero_default:false:0:true + diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw-4,0,2_2.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw-4,0,2_2.txt new file mode 100644 index 0000000..ec14331 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_0/mw-4,0,2_2.txt @@ -0,0 +1,4 @@ +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:global +# + diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_1/mw$default_1.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_1/mw$default_1.txt new file mode 100644 index 0000000..5bd4f09 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.rsninja.dev/dim_1/mw$default_1.txt @@ -0,0 +1,10 @@ +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:global +# +waypoint:e:E:392:49:-2200:2:false:0:gui.xaero_default:false:0:false +waypoint:XP Farm:X:375:1:-8:0:false:0:gui.xaero_default:false:0:false +waypoint:Portal:P:0:68:0:5:false:0:gui.xaero_default:false:0:false +waypoint:another portal:A:289:60:1365:2:false:0:gui.xaero_default:false:0:false +waypoint:island:I:-576:62:1050:3:false:0:gui.xaero_default:false:0:false +waypoint:island:I:-576:62:1050:12:false:0:gui.xaero_default:false:0:false + From c538d401c0f75e8e5c69408508c989b857b0e76a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 23 Oct 2023 12:43:56 -0400 Subject: [PATCH 187/326] Add script to generate scp acls --- configs/scripts/scp-make-upload-acl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 configs/scripts/scp-make-upload-acl diff --git a/configs/scripts/scp-make-upload-acl b/configs/scripts/scp-make-upload-acl new file mode 100755 index 0000000..faf4f1e --- /dev/null +++ b/configs/scripts/scp-make-upload-acl @@ -0,0 +1,17 @@ +#! /bin/sh +set -e + +# Require an argument containing a directory +if [ $# -ne 3 ]; then + echo "Usage: scp-make-upload-acl " + exit 1 +fi + +# Require the directory to exist +if [ ! -d "$1" ]; then + echo "Directory $1 does not exist" + exit 1 +fi + +# If all is ok, then print out the authorized_keys line that restricts that key to that directory +echo "command=\"scp -t $1\",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding $2 $3" From 1770c2978df9c1fc43091d8f84ba048ce9880058 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 25 Oct 2023 15:42:37 -0400 Subject: [PATCH 188/326] dl opt sc --- configs/scripts/deadline-read-options | 44 +++++++++++++++++++++++++++ configs/ssh/config | 8 ++--- 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 configs/scripts/deadline-read-options diff --git a/configs/scripts/deadline-read-options b/configs/scripts/deadline-read-options new file mode 100644 index 0000000..717d296 --- /dev/null +++ b/configs/scripts/deadline-read-options @@ -0,0 +1,44 @@ +#! /usr/bin/env python +import argparse +import sys +import configparser + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + description="Nicely lists the options stored in a Deadline .options file" + ) + ap.add_argument("options_file", type=str, help="The .options file to read") + ap.add_argument( + "--show-types", action="store_true", help="Show the type of each option" + ) + ap.add_argument( + "--show-defaults", + action="store_true", + help="Show the default value of each option", + ) + args = ap.parse_args() + + # Read the file + with open(args.options_file, "r") as f: + config_string = f.read() + + # Parse the file + config = configparser.ConfigParser() + config.read_string(config_string) + + # List each option + for section in config.sections(): + print(f"{section}{'*' if bool(config[section].get('Required', False)) else ''}: {config[section].get('Description', 'No description')}") + if args.show_types: + print(f" Type: {config[section].get('Type', 'No type')}") + if args.show_defaults: + print(f" Default: {config[section].get('Default', 'No default')}") + + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/ssh/config b/configs/ssh/config index b005789..879f16b 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -16,11 +16,11 @@ Host github.com gist.github.com # IdentityFile %d/.ssh/id_rsa # Home network -Host unifi - HostName DreamMachinePro.local +Host unifi + HostName dreammachinepro.local User root - PreferredAuthentications password - PubkeyAuthentication no + #PreferredAuthentications password + # PubkeyAuthentication no Host ewpratten-steamdeck HostName ewpratten-steamdeck.local From f948885c68a289f8ff4c74bce27b7d38fb7c0f7d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 25 Oct 2023 15:45:52 -0400 Subject: [PATCH 189/326] handle no default --- configs/scripts/deadline-read-options | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/scripts/deadline-read-options b/configs/scripts/deadline-read-options index 717d296..fb622c5 100644 --- a/configs/scripts/deadline-read-options +++ b/configs/scripts/deadline-read-options @@ -33,8 +33,8 @@ def main() -> int: print(f"{section}{'*' if bool(config[section].get('Required', False)) else ''}: {config[section].get('Description', 'No description')}") if args.show_types: print(f" Type: {config[section].get('Type', 'No type')}") - if args.show_defaults: - print(f" Default: {config[section].get('Default', 'No default')}") + if args.show_defaults and "Default" in config[section]: + print(f" Default: {config[section]['Default']}") return 0 From 779c5bb99fb3939297a645cbdbe8224fac663406 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 28 Oct 2023 12:11:13 -0400 Subject: [PATCH 190/326] Update chmod and ssh confg --- configs/scripts/deadline-read-options | 0 configs/ssh/config | 4 ++++ 2 files changed, 4 insertions(+) mode change 100644 => 100755 configs/scripts/deadline-read-options diff --git a/configs/scripts/deadline-read-options b/configs/scripts/deadline-read-options old mode 100644 new mode 100755 diff --git a/configs/ssh/config b/configs/ssh/config index 879f16b..99754c1 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -71,6 +71,10 @@ Host *.ring.nlnog.net # SDF.org Host sdf.org *.sdf.org user ewpratten +Host sdf + HostName sdf.org +Host otaku + HostName otaku.sdf.org # Guru Host *.gurustudio.com From 000d33b961824ab5003856cba9e632d6fd1de9d5 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 28 Oct 2023 13:49:34 -0400 Subject: [PATCH 191/326] Add a script for installing neovim from source --- configs/scripts/install-nvim-from-source | 39 ++++++++++++++++++++++++ configs/shells/bash/macros.sh | 1 + 2 files changed, 40 insertions(+) create mode 100755 configs/scripts/install-nvim-from-source diff --git a/configs/scripts/install-nvim-from-source b/configs/scripts/install-nvim-from-source new file mode 100755 index 0000000..c424413 --- /dev/null +++ b/configs/scripts/install-nvim-from-source @@ -0,0 +1,39 @@ +#! /bin/bash +set -e + +echo "You have chosen to isntall neovim from source." + +# If ~/src/neovim doesn't exist, clone a fresh copy +cd ~/src +if [ ! -d ~/src/neovim ]; then + git clone https://github.com/neovim/neovim +fi +cd neovim + +# Handle branch checkout +echo "Do you want to switch to the stable branch? (y/n)" +read -r -n 1 response +if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then + git checkout stable +fi + +# Figure out the appropriate make command. +if [ -x "$(command -v gmake)" ]; then + MAKE_CMD=gmake +else + MAKE_CMD=make +fi + +# Determine the install prefix +NVIM_INSTALL_PREFIX=${NVIM_INSTALL_PREFIX:-$HOME/.local} + +# Build +echo "Building neovim..." +$MAKE_CMD CMAKE_BUILD_TYPE=Release CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=$NVIM_INSTALL_PREFIX" + +# Install +echo "Would you like to install neovim? (y/n)" +read -r -n 1 response +if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then + $MAKE_CMD install +fi diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 0f5e54b..200e0ef 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -19,6 +19,7 @@ alias sheridan-rdp='firefox --new-window "ext+container:name=College&url=https:/ alias git-diff-nvim="git diff | nvim -R -d -c 'set filetype=diff' -" alias yk-totp="ykman oath accounts code" alias flush-dns-cache="sudo systemd-resolve --flush-caches" +alias which-ls="ls -la $(which ls)" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From dc4cea38bed94fed89b7a3716c605b2d95f0a8f4 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 28 Oct 2023 13:54:44 -0400 Subject: [PATCH 192/326] use nsf --- install-linux.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/install-linux.sh b/install-linux.sh index da8ea02..1a63f25 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -79,17 +79,17 @@ if type -p chown > /dev/null; then chown "$USER:$USER" "$HOME/.ssh/config"; fi # Configure (neo)Vim ln -sf $EWCONFIG_ROOT/configs/nvim/init.vim ~/.config/nvim/init.vim -unlink ~/.config/nvim/pack || true; ln -sf $EWCONFIG_ROOT/configs/nvim/pack ~/.config/nvim/pack -unlink ~/.config/nvim/third_party || true; ln -sf $EWCONFIG_ROOT/configs/nvim/third_party ~/.config/nvim/third_party +ln -snf $EWCONFIG_ROOT/configs/nvim/pack ~/.config/nvim/pack +ln -snf $EWCONFIG_ROOT/configs/nvim/third_party ~/.config/nvim/third_party # Nautilus right-click scripts ln -sf $EWCONFIG_ROOT/configs/nautilus/scripts/* ~/.local/share/nautilus/scripts/ # Tabset configs -unlink ~/.config/tabset || true; ln -sf $EWCONFIG_ROOT/configs/tabset ~/.config/tabset +ln -nsf $EWCONFIG_ROOT/configs/tabset ~/.config/tabset # Rofi configs -unlink ~/.config/rofi || true; ln -sf $EWCONFIG_ROOT/configs/rofi ~/.config/rofi +ln -nsf $EWCONFIG_ROOT/configs/rofi ~/.config/rofi # Cargo ln -sf $EWCONFIG_ROOT/configs/cargo/config.toml ~/.cargo/config.toml @@ -104,7 +104,7 @@ ln -sf $EWCONFIG_ROOT/configs/user-tmpfiles.d/* ~/.config/user-tmpfiles.d/ ln -sf $EWCONFIG_ROOT/configs/logid/logid.cfg ~/.config/logid/logid.cfg # Minecraft global configs -unlink ~/.config/minecraft || true; ln -sf $EWCONFIG_ROOT/configs/minecraft ~/.config/minecraft +ln -nsf $EWCONFIG_ROOT/configs/minecraft ~/.config/minecraft if [ -d ~/.var/app/org.prismlauncher.PrismLauncher ]; then flatpak override --user --filesystem=~/.config/minecraft org.prismlauncher.PrismLauncher fi From d1af95e3ae7651471e31c9cc1ce395d914d77d5a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 28 Oct 2023 13:55:40 -0400 Subject: [PATCH 193/326] change bash path --- configs/scripts/install-nvim-from-source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/scripts/install-nvim-from-source b/configs/scripts/install-nvim-from-source index c424413..8ede3be 100755 --- a/configs/scripts/install-nvim-from-source +++ b/configs/scripts/install-nvim-from-source @@ -1,4 +1,4 @@ -#! /bin/bash +#! /usr/bin/env bash set -e echo "You have chosen to isntall neovim from source." From 918d32b6fa57debd14a1157a089fd76699620b2d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 28 Oct 2023 14:11:51 -0400 Subject: [PATCH 194/326] nvim appimage script --- configs/scripts/install-nvim-appimage | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 configs/scripts/install-nvim-appimage diff --git a/configs/scripts/install-nvim-appimage b/configs/scripts/install-nvim-appimage new file mode 100755 index 0000000..564536d --- /dev/null +++ b/configs/scripts/install-nvim-appimage @@ -0,0 +1,9 @@ +#! /bin/sh +set -ex + +# Download the appimage to .local/bin +mkdir -p ~/.local/bin +wget https://github.com/neovim/neovim/releases/download/stable/nvim.appimage -O ~/.local/bin/nvim + +# Make it executable +chmod +x ~/.local/bin/nvim From a6ee1909a122c1fb4029031ff9b9be87ee77fe39 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 09:59:50 -0400 Subject: [PATCH 195/326] python3 aliasing --- configs/shells/bash/.bashrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 5b43631..8ebca54 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -17,3 +17,12 @@ export PS1="(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" # If found, load studio python if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH"; fi + +# If `python --version` starts with `Python 3` +if [[ $(python --version) == Python\ 3* ]]; then + # If we don't have python3 in our path + if ! command -v python3 &> /dev/null; then + # Make an alias for python3 + alias python3=python + fi +fi From ffcfe33f02dc6d7fcef97dd9ea95e93abef4caa1 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:11:53 -0400 Subject: [PATCH 196/326] guru shell --- configs/shells/bash/.bashrc | 2 +- configs/shells/bash/macros.sh | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 8ebca54..5038e0b 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -13,7 +13,7 @@ export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" # A basic prompt to display user@host dir sign -export PS1="(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" +export PS1="$PS1_CTX(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" # If found, load studio python if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH"; fi diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 200e0ef..b1f7604 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -192,3 +192,10 @@ ewconfig-pull-zip(){ # Return to the original directory cd $cwd } + +# Pop a shell inside Guru env +guru-shell() { + PYTHONPATH="//qs//resources/studio/studio2023/env:$PYTHONPATH" \ + PS1_CTX="(guru) " \ + bash +} \ No newline at end of file From cb4104318d5a164eb6980fdb7d1dfb3c9435e949 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:15:34 -0400 Subject: [PATCH 197/326] improve ctx --- configs/shells/bash/.bashrc | 2 +- configs/shells/bash/macros.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 5038e0b..1e99044 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -13,7 +13,7 @@ export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" # A basic prompt to display user@host dir sign -export PS1="$PS1_CTX(bash) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" +export PS1="(${PS1_CTX:-bash}) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" # If found, load studio python if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH"; fi diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index b1f7604..651e072 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -196,6 +196,6 @@ ewconfig-pull-zip(){ # Pop a shell inside Guru env guru-shell() { PYTHONPATH="//qs//resources/studio/studio2023/env:$PYTHONPATH" \ - PS1_CTX="(guru) " \ + PS1_CTX="guru bash" \ bash } \ No newline at end of file From f21c206d0eb192e1e7ab7b19b823ac9d167b4789 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:16:37 -0400 Subject: [PATCH 198/326] Fix path --- configs/shells/bash/macros.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 651e072..508020c 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -195,7 +195,7 @@ ewconfig-pull-zip(){ # Pop a shell inside Guru env guru-shell() { - PYTHONPATH="//qs//resources/studio/studio2023/env:$PYTHONPATH" \ + PYTHONPATH="//qs/resources/studio/studio2023/env:$PYTHONPATH" \ PS1_CTX="guru bash" \ bash } \ No newline at end of file From 6561351220b4b405914d6bf64ccef016469d2306 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:19:09 -0400 Subject: [PATCH 199/326] Add on to pythonpath --- configs/shells/bash/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 508020c..ef2603f 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -196,6 +196,7 @@ ewconfig-pull-zip(){ # Pop a shell inside Guru env guru-shell() { PYTHONPATH="//qs/resources/studio/studio2023/env:$PYTHONPATH" \ + PYTHONPATH="//qs/resources/studio/studio2023:$PYTHONPATH" \ PS1_CTX="guru bash" \ bash } \ No newline at end of file From d57dcdae0cb174d7fb0f1c857b26dbd84044d464 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:29:03 -0400 Subject: [PATCH 200/326] make better use of the guru shell tool --- configs/shells/bash/.bashrc | 11 ++--------- configs/shells/bash/macros.sh | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 1e99044..342546e 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -16,13 +16,6 @@ export PATH="$HOME/.local/bin:$PATH" export PS1="(${PS1_CTX:-bash}) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" # If found, load studio python -if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH"; fi +# if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH"; fi + -# If `python --version` starts with `Python 3` -if [[ $(python --version) == Python\ 3* ]]; then - # If we don't have python3 in our path - if ! command -v python3 &> /dev/null; then - # Make an alias for python3 - alias python3=python - fi -fi diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index ef2603f..7e794ad 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -46,6 +46,16 @@ alias whois-ripe="whois -h whois.ripe.net" if [ -x "$(command -v nvim)" ]; then alias vim="nvim"; fi if [ -x "$(command -v neomutt)" ]; then alias mutt="neomutt"; fi +# Python aliases +# If `python --version` starts with `Python 3` +if [[ $(python --version) == Python\ 3* ]]; then + # If we don't have python3 in our path + if ! command -v python3 &> /dev/null; then + # Make an alias for python3 + alias python3=python + fi +fi + # Kill via pgrep nkill() { if [ $# != 1 ]; then @@ -195,8 +205,16 @@ ewconfig-pull-zip(){ # Pop a shell inside Guru env guru-shell() { - PYTHONPATH="//qs/resources/studio/studio2023/env:$PYTHONPATH" \ - PYTHONPATH="//qs/resources/studio/studio2023:$PYTHONPATH" \ + # Figure out the appropriate prefix + if [ $(uname -o | grep -c Msys) -gt 0 ]; then + s_drive="s://" + else + s_drive="//qs/resources" + fi + + PYTHONPATH="$s_drive/studio/studio2023/env:$PYTHONPATH" \ + PYTHONPATH="$s_drive/studio/studio2023:$PYTHONPATH" \ + PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH" \ PS1_CTX="guru bash" \ bash } \ No newline at end of file From 06293dbaf7853a870ac23efcbb49d07457f579da Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:31:45 -0400 Subject: [PATCH 201/326] proper pathsep --- configs/shells/bash/macros.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 7e794ad..a560692 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -207,14 +207,16 @@ ewconfig-pull-zip(){ guru-shell() { # Figure out the appropriate prefix if [ $(uname -o | grep -c Msys) -gt 0 ]; then - s_drive="s://" + s_drive="S://" + pathsep=";" else s_drive="//qs/resources" + pathsep=":" fi - PYTHONPATH="$s_drive/studio/studio2023/env:$PYTHONPATH" \ - PYTHONPATH="$s_drive/studio/studio2023:$PYTHONPATH" \ - PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH" \ + PYTHONPATH="$s_drive/studio/studio2023/env$pathsep$PYTHONPATH" \ + PYTHONPATH="$s_drive/studio/studio2023$pathsep$PYTHONPATH" \ + PATH="/c/Programs/software/win/core/python/python_3.7.7$pathsep$PATH" \ PS1_CTX="guru bash" \ bash } \ No newline at end of file From 0f1994f2a007402a98fd23fbae3e9cf8654bc02a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:41:45 -0400 Subject: [PATCH 202/326] More logic --- configs/shells/bash/macros.sh | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index a560692..7545b2b 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -205,6 +205,12 @@ ewconfig-pull-zip(){ # Pop a shell inside Guru env guru-shell() { + # If //qs does not exist + if [ ! -d "//qs" ]; then + echo "This command must be executed on a studio machine!" + return 1 + fi + # Figure out the appropriate prefix if [ $(uname -o | grep -c Msys) -gt 0 ]; then s_drive="S://" @@ -214,9 +220,20 @@ guru-shell() { pathsep=":" fi - PYTHONPATH="$s_drive/studio/studio2023/env$pathsep$PYTHONPATH" \ - PYTHONPATH="$s_drive/studio/studio2023$pathsep$PYTHONPATH" \ + # Ask if we want to use the development env + echo "Do you want to use the development environment? (Y/n)" + read dev_env + if [ "$dev_env" == "n" ]; then + studio2023_path="studio/studio2023" + ps1_mode="" + else + studio2023_path="development/epratten/studio/studio2023" + ps1_mode="-dev" + fi + + PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" \ + PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" \ PATH="/c/Programs/software/win/core/python/python_3.7.7$pathsep$PATH" \ - PS1_CTX="guru bash" \ + PS1_CTX="guru$ps1_mode bash" \ bash } \ No newline at end of file From 4fb1f446ae83a0f493290ecb3afe28487609336d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:43:10 -0400 Subject: [PATCH 203/326] Fix slash count --- configs/shells/bash/macros.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 7545b2b..76f4dd8 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -213,7 +213,7 @@ guru-shell() { # Figure out the appropriate prefix if [ $(uname -o | grep -c Msys) -gt 0 ]; then - s_drive="S://" + s_drive="S:/" pathsep=";" else s_drive="//qs/resources" From a88249ce2bb60af4bfa6e7f12827898249ad26b4 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:46:52 -0400 Subject: [PATCH 204/326] remove old conf file --- install.conf.yaml | 107 ---------------------------------------------- 1 file changed, 107 deletions(-) delete mode 100644 install.conf.yaml diff --git a/install.conf.yaml b/install.conf.yaml deleted file mode 100644 index ef3edea..0000000 --- a/install.conf.yaml +++ /dev/null @@ -1,107 +0,0 @@ -- defaults: - link: - relink: true - -- clean: ["~"] - -- create: - # Common organizational dirs - - ~/Downloads - - ~/bin - - ~/projects - - ~/services - - ~/src - - ~/www - - ~/pkg - # Config dirs - - ~/.config/nvim - - ~/.config/termux - - ~/.config/logid - - ~/.config/systemd/user - - ~/.config/autostart - - ~/.config/git - - ~/.cargo - - ~/.config/user-tmpfiles.d - - ~/.config/blender/3.6/scripts/addons - # Program plugins - - ~/.local/share/nautilus/scripts/ - - ~/houdini19.5 - -- link: - # Git - ~/.gitconfig: configs/git/.gitconfig - ~/.config/git/.mailmap: configs/git/.mailmap - ~/.ssh/allowed_signers: configs/ssh/allowed_signers - - # Shell - ~/.zshrc: - path: configs/zsh/.zshrc - force: true - ~/.bashrc: - path: configs/bash/.bashrc - force: true - - # Vim - ~/.config/nvim/init.vim: configs/nvim/init.vim - ~/.config/nvim/pack: configs/nvim/pack - ~/.config/nvim/third_party: configs/nvim/third_party - - # Scripts - ~/bin/catto: configs/scripts/catto - ~/bin/aspath: configs/scripts/aspath - ~/bin/fetch-steamdeck-screenshots: configs/scripts/fetch-steamdeck-screenshots - ~/bin/houdini-tool: configs/scripts/houdini-tool.py - ~/bin/hython-latest: configs/scripts/hython-latest - ~/bin/usdnc-to-usd: configs/scripts/usdnc-to-usd.py - ~/bin/guru-vpn: configs/scripts/guru-vpn.py - ~/bin/wg-handshakes: configs/scripts/wg-handshakes.py - ~/bin/wg-genzone: configs/scripts/wg-genzone.py - ~/bin/ewp-sendmail: configs/scripts/ewp-sendmail.py - - # Nautilus right-click scripts - ~/.local/share/nautilus/scripts/Copy to web: - path: configs/nautilus/scripts/Copy to web - mode: 755 - ~/.local/share/nautilus/scripts/Open in Video Trimmer: - path: configs/nautilus/scripts/Open in Video Trimmer - mode: 755 - ~/.local/share/nautilus/scripts/Open with USDView: - path: configs/nautilus/scripts/Open with USDView - mode: 755 - - # XDG Autostart - ~/.config/autostart/gnome-keyring-ssh.desktop: configs/autostart/gnome-keyring-ssh.desktop - ~/.config/autostart/logid.desktop: configs/autostart/logid.desktop - - # Blender Addons - ~/.config/blender/3.6/scripts/addons/y_aligned_camera.py: configs/blender/3.x/scripts/addons/y_aligned_camera.py - - # Others - ~/.config/tabset: configs/tabset - ~/.config/rofi: configs/rofi - # ~/.local/share/remmina: configs/remmina/hosts - ~/.cargo/config.toml: configs/cargo/config.toml - ~/.config/termux/termux.properties: configs/termux/termux.properties - ~/.config/user-tmpfiles.d/discord-rpc.conf: configs/user-tmpfiles.d/discord-rpc.conf - ~/.config/logid/logid.cfg: configs/logid/logid.cfg - ~/houdini19.5/scripts: configs/houdini19.5/scripts - ~/sln: solutions - -- shell: - # Make sure we have our git modules - - [git submodule update --init --recursive, Installing submodules] - # Install SSH config - - [sh ./helpers/install-ssh-config.sh, Installing SSH config] - # Ensure that all downloaded scripts are executable - - [chmod +x configs/scripts/*, Making bin scripts executable] - - [chmod +x configs/nautilus/scripts/*, Making nautilus scripts executable] - - [chmod +x solutions/*, Making solution scripts executable] - # Configure GNOME - - [sh ./helpers/configure-gnome.sh, Configuring GNOME] - # Configure Termux if on Android - - [termux-reload-settings || true, Trying to reload Termux] - # Configure Git - - [ - bash ./helpers/git-config-features.sh, - Setting up optional git-config features, - ] From 54190e819bbec541008b3ecaf06bb2ed3e93cdf6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:54:29 -0400 Subject: [PATCH 205/326] move guru shell to its ownd file --- configs/scripts/guru-shell | 41 +++++++++++++++++++++++++++++++++++ configs/shells/bash/macros.sh | 41 ++++++----------------------------- 2 files changed, 48 insertions(+), 34 deletions(-) create mode 100644 configs/scripts/guru-shell diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell new file mode 100644 index 0000000..e30d38c --- /dev/null +++ b/configs/scripts/guru-shell @@ -0,0 +1,41 @@ +#! /bin/bash +set -e + +# If //qs does not exist +if [ ! -d "//qs" ]; then + echo "This command must be executed on a studio machine!" + return 1 +fi + +# Figure out the appropriate prefix +if [ $(uname -o | grep -c Msys) -gt 0 ]; then + s_drive="S:/" + pathsep=";" +else + s_drive="//qs/resources" + pathsep=":" +fi + +# Ask if we want to use the development env +echo "Do you want to use the development environment? (Y/n)" +read dev_env +if [ "$dev_env" == "n" ]; then + studio2023_path="studio/studio2023" + ps1_mode="" +else + studio2023_path="development/epratten/studio/studio2023" + ps1_mode="-dev" +fi + +# Set PYTHONPATH based on the data we learned +PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" +PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" + +# Update the PATH to point to the studio's install of python +PATH="/c/Programs/software/win/core/python/python_3.7.7$pathsep$PATH" + +# Configure the prompt +PS1_CTX="guru$ps1_mode bash" + +# Finally, start bash +bash \ No newline at end of file diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 76f4dd8..df4352a 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -203,37 +203,10 @@ ewconfig-pull-zip(){ cd $cwd } -# Pop a shell inside Guru env -guru-shell() { - # If //qs does not exist - if [ ! -d "//qs" ]; then - echo "This command must be executed on a studio machine!" - return 1 - fi - - # Figure out the appropriate prefix - if [ $(uname -o | grep -c Msys) -gt 0 ]; then - s_drive="S:/" - pathsep=";" - else - s_drive="//qs/resources" - pathsep=":" - fi - - # Ask if we want to use the development env - echo "Do you want to use the development environment? (Y/n)" - read dev_env - if [ "$dev_env" == "n" ]; then - studio2023_path="studio/studio2023" - ps1_mode="" - else - studio2023_path="development/epratten/studio/studio2023" - ps1_mode="-dev" - fi - - PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" \ - PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" \ - PATH="/c/Programs/software/win/core/python/python_3.7.7$pathsep$PATH" \ - PS1_CTX="guru$ps1_mode bash" \ - bash -} \ No newline at end of file +# Temporairly hop to the ewconfig directory to run a command +ewconfig-run() { + cwd=$(pwd) + cd ~/.config/ewconfig + $@ + cd $cwd +} From 2692667af061cd0b97f2128f3d00d2728dd1da04 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:56:37 -0400 Subject: [PATCH 206/326] use exports --- configs/scripts/guru-shell | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell index e30d38c..5d46db3 100644 --- a/configs/scripts/guru-shell +++ b/configs/scripts/guru-shell @@ -28,14 +28,14 @@ else fi # Set PYTHONPATH based on the data we learned -PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" -PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" +export PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" +export PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" # Update the PATH to point to the studio's install of python -PATH="/c/Programs/software/win/core/python/python_3.7.7$pathsep$PATH" +export PATH="/c/Programs/software/win/core/python/python_3.7.7$pathsep$PATH" # Configure the prompt -PS1_CTX="guru$ps1_mode bash" +export PS1_CTX="guru$ps1_mode bash" # Finally, start bash bash \ No newline at end of file From f700182fd9019d7022d2dbf2ff5c4f184d12a4f8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 10:58:09 -0400 Subject: [PATCH 207/326] fix py aliases --- configs/shells/bash/macros.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index df4352a..19442e2 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -46,13 +46,15 @@ alias whois-ripe="whois -h whois.ripe.net" if [ -x "$(command -v nvim)" ]; then alias vim="nvim"; fi if [ -x "$(command -v neomutt)" ]; then alias mutt="neomutt"; fi -# Python aliases -# If `python --version` starts with `Python 3` -if [[ $(python --version) == Python\ 3* ]]; then - # If we don't have python3 in our path - if ! command -v python3 &> /dev/null; then - # Make an alias for python3 - alias python3=python +# If python exists, configure an alias for python3 if needed +if [ -x "$(command -v python)" ]; then + # If `python --version` starts with `Python 3` + if [[ $(python --version) == Python\ 3* ]]; then + # If we don't have python3 in our path + if ! command -v python3 &> /dev/null; then + # Make an alias for python3 + alias python3=python + fi fi fi From 954466801e3db79b2dc0379e32367ac9cc4f9081 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 11:00:38 -0400 Subject: [PATCH 208/326] update --- configs/scripts/guru-shell | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell index 5d46db3..380b182 100644 --- a/configs/scripts/guru-shell +++ b/configs/scripts/guru-shell @@ -17,7 +17,7 @@ else fi # Ask if we want to use the development env -echo "Do you want to use the development environment? (Y/n)" +echo -n "Do you want to use the development environment? (Y/n)" read dev_env if [ "$dev_env" == "n" ]; then studio2023_path="studio/studio2023" @@ -32,7 +32,9 @@ export PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" export PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" # Update the PATH to point to the studio's install of python -export PATH="/c/Programs/software/win/core/python/python_3.7.7$pathsep$PATH" +if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then + export PATH="C://Programs/software/win/core/python/python_3.7.7$pathsep$PATH" +fi # Configure the prompt export PS1_CTX="guru$ps1_mode bash" From 0ccbc68c17500572c4ffc760c5b47136708c8277 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 11:02:30 -0400 Subject: [PATCH 209/326] fix sep --- configs/scripts/guru-shell | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell index 380b182..7f44d8b 100644 --- a/configs/scripts/guru-shell +++ b/configs/scripts/guru-shell @@ -33,7 +33,7 @@ export PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" # Update the PATH to point to the studio's install of python if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then - export PATH="C://Programs/software/win/core/python/python_3.7.7$pathsep$PATH" + export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH" fi # Configure the prompt From 3f50b3af9c0eabbc69ea245aa56a95325e77db95 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 11:06:31 -0400 Subject: [PATCH 210/326] fix dev path --- configs/scripts/guru-shell | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell index 7f44d8b..c229665 100644 --- a/configs/scripts/guru-shell +++ b/configs/scripts/guru-shell @@ -23,7 +23,7 @@ if [ "$dev_env" == "n" ]; then studio2023_path="studio/studio2023" ps1_mode="" else - studio2023_path="development/epratten/studio/studio2023" + studio2023_path="development/epratten/studio2023" ps1_mode="-dev" fi From 0aaf949dbf8d4d23e0ee89764680f4e01245bfe2 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 11:07:51 -0400 Subject: [PATCH 211/326] Add a util to dump pythonpath --- configs/scripts/show-pythonpath | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 configs/scripts/show-pythonpath diff --git a/configs/scripts/show-pythonpath b/configs/scripts/show-pythonpath new file mode 100644 index 0000000..13271c5 --- /dev/null +++ b/configs/scripts/show-pythonpath @@ -0,0 +1,5 @@ +#! /usr/bin/env python +import sys + +for entry in sys.path: + print(" - " + entry) From e99c5854b9d032223d1b38cab538c5f2a043a553 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 11:12:38 -0400 Subject: [PATCH 212/326] Allow global debugging --- configs/scripts/guru-shell | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell index c229665..bdd2df0 100644 --- a/configs/scripts/guru-shell +++ b/configs/scripts/guru-shell @@ -27,6 +27,13 @@ else ps1_mode="-dev" fi +# Ask if we want to force debugging for all processes +echo -n "Do you want to force debugging for all processes? (y/N)" +read force_debug +if [ "$force_debug" == "y" ]; then + export GURU_DEBUG=1 +fi + # Set PYTHONPATH based on the data we learned export PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" export PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" From 84fa07ec87bde9d42f5dd334e7ae0156f818cc8e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 11:18:47 -0400 Subject: [PATCH 213/326] gl3 alias --- configs/scripts/guru-shell | 6 ++++-- configs/shells/bash/macros.sh | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell index bdd2df0..bcf5560 100644 --- a/configs/scripts/guru-shell +++ b/configs/scripts/guru-shell @@ -35,8 +35,9 @@ if [ "$force_debug" == "y" ]; then fi # Set PYTHONPATH based on the data we learned -export PYTHONPATH="$s_drive/$studio2023_path/env$pathsep$PYTHONPATH" -export PYTHONPATH="$s_drive/$studio2023_path$pathsep$PYTHONPATH" +export GURU_PYTHON_ROOT="$s_drive/$studio2023_path" +export PYTHONPATH="$GURU_PYTHON_ROOT/env$pathsep$PYTHONPATH" +export PYTHONPATH="$GURU_PYTHON_ROOT$pathsep$PYTHONPATH" # Update the PATH to point to the studio's install of python if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then @@ -47,4 +48,5 @@ fi export PS1_CTX="guru$ps1_mode bash" # Finally, start bash +export EWP_IN_GURU_ENVIRONMENT=1 bash \ No newline at end of file diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 19442e2..55d069b 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -58,6 +58,11 @@ if [ -x "$(command -v python)" ]; then fi fi +# If we are running in a studio environment +if [ ! -z "$EWP_IN_GURU_ENVIRONMENT" ]; then + alias guru_launcher3="python $GURU_PYTHON_ROOT/env/guru_launcher3.py" +fi + # Kill via pgrep nkill() { if [ $# != 1 ]; then From 4379192658225071afd38ad8e7782160182751e0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 30 Oct 2023 22:38:56 -0400 Subject: [PATCH 214/326] update perms --- configs/scripts/guru-shell | 0 configs/scripts/show-pythonpath | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 configs/scripts/guru-shell mode change 100644 => 100755 configs/scripts/show-pythonpath diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell old mode 100644 new mode 100755 diff --git a/configs/scripts/show-pythonpath b/configs/scripts/show-pythonpath old mode 100644 new mode 100755 From 831fdc799ee23abc5e25abc53547cae41b0c9717 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 1 Nov 2023 09:33:26 -0400 Subject: [PATCH 215/326] rdns alias --- configs/shells/bash/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 55d069b..2275492 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -20,6 +20,7 @@ alias git-diff-nvim="git diff | nvim -R -d -c 'set filetype=diff' -" alias yk-totp="ykman oath accounts code" alias flush-dns-cache="sudo systemd-resolve --flush-caches" alias which-ls="ls -la $(which ls)" +alias rdns="dig +short -x" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From 9fee4111ec166c01c2da69d6a718e108dd5cda7f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 1 Nov 2023 12:09:42 -0400 Subject: [PATCH 216/326] Build script that can pull gitlab issues to trello --- configs/scripts/guru-sync-issues | 199 +++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100755 configs/scripts/guru-sync-issues diff --git a/configs/scripts/guru-sync-issues b/configs/scripts/guru-sync-issues new file mode 100755 index 0000000..c968415 --- /dev/null +++ b/configs/scripts/guru-sync-issues @@ -0,0 +1,199 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import requests +import json +from dataclasses import dataclass, field +from pathlib import Path +from typing import List, Optional, Dict, Any +from enum import Enum, auto +from datetime import datetime + +logger = logging.getLogger(__name__) + +GITLAB_PAT_FILE_PATH = Path("~/.config/guru-sync-issues/gitlab_pat.txt").expanduser() +GITLAB_ENDPOINT = "http://gitlab.guru-domain.gurustudio.com/api/v4" +MY_USER_ID = 64 +TRELLO_API_TOKEN_FILE_PATH = Path( + "~/.config/guru-sync-issues/trello_api_token.txt" +).expanduser() +TRELLO_API_KEY = "fba640a85f15c91e93e6b3f88e59489c" +TRELLO_BOARD = "tw3Cn3L6" +TRELLO_TODO_LIST = "6348a3ce5208f505b61d29bf" +TRELLO_LABELS = { + "GURU": "64e03ac77d27032282436d28" +} + +# Load the PAT +try: + with open(GITLAB_PAT_FILE_PATH) as f: + GITLAB_PAT = f.read().strip() +except FileNotFoundError: + logger.error( + f"Could not find GitLab PAT file at {GITLAB_PAT_FILE_PATH}. Please create it and try again." + ) + sys.exit(1) + +# Load Trello key +try: + with open(TRELLO_API_TOKEN_FILE_PATH) as f: + TRELLO_API_TOKEN = f.read().strip() +except FileNotFoundError: + logger.error( + f"Could not find Trello API key file at {TRELLO_API_TOKEN_FILE_PATH}. Please create it and try again." + ) + sys.exit(1) + +TrelloCardId = str + + +class IssueState(Enum): + OPEN = "opened" + CLOSED = "closed" + + +@dataclass +class GitLabIssue: + title: str + issue_id: int + global_id: int + state: IssueState + created: datetime + updated: datetime + web_url: str + reference_string: str + due_date: Optional[datetime] = None + + +def get_personal_gitlab_issues(user_id: int = MY_USER_ID) -> List[GitLabIssue]: + # Make an API call + response = requests.get( + f"{GITLAB_ENDPOINT}/issues", + params={ + "assignee_id": user_id, + "private_token": GITLAB_PAT, + "per_page": 100, + "scope": "all", + }, + ) + response.raise_for_status() + + # Parse the response + output = [] + for issue in response.json(): + output.append( + GitLabIssue( + title=issue["title"], + issue_id=issue["iid"], + global_id=issue["id"], + state=IssueState(issue["state"]), + created=datetime.fromisoformat(issue["created_at"]), + updated=datetime.fromisoformat(issue["updated_at"]), + web_url=issue["web_url"], + reference_string=issue["references"]["full"], + due_date=datetime.fromisoformat(issue["due_date"]) + if issue["due_date"] + else None, + ) + ) + + return output + + +def get_all_trello_cards() -> List[Dict[str, Any]]: + # Get a list of cards on the board + response = requests.get( + f"https://api.trello.com/1/boards/{TRELLO_BOARD}/cards", + params={ + "key": TRELLO_API_KEY, + "token": TRELLO_API_TOKEN, + }, + ) + response.raise_for_status() + return response.json() + + +def find_or_create_trello_issue_for( + trello_cards: List[Dict[str, Any]], gitlab_issue: GitLabIssue +) -> TrelloCardId: + # Look for a card that matches the issue + for card in trello_cards: + # Check the first line of the description for metadata + description = card["desc"] + desc_first_line = description.split("\n")[0] + if not desc_first_line.startswith("**Sync Metadata:** "): + continue + + # Parse the metadata + metadata = json.loads(desc_first_line.split("`")[1]) + + # Check if the card matches + if metadata.get("ns") == "guru-gitlab" and ( + gitlab_issue.global_id in metadata.get("ids", []) + ): + print(card["labels"], card["idLabels"]) + logger.info(f"Found matching card {card['id']}") + return card["id"] + + # Build the description + card_description = "\n\n".join( + [ + f"**Sync Metadata:** `{json.dumps({'ns': 'guru-gitlab', 'ids': [gitlab_issue.global_id]})}`", + f"**GitLab Issue:** [`{gitlab_issue.reference_string}`]({gitlab_issue.web_url})\n", + "---" + ] + ) + + # Make a new card + response = requests.post( + "https://api.trello.com/1/cards", + params={ + "idList": TRELLO_TODO_LIST, + "name": gitlab_issue.title, + "desc": card_description, + "idLabels": ",".join([TRELLO_LABELS["GURU"]]), + "pos": "top", + "key": TRELLO_API_KEY, + "token": TRELLO_API_TOKEN, + }, + ) + response.raise_for_status() + + return response.json()["id"] + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(description="Syncs issues from GitLab to Trello") + + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Find all issues + issues = get_personal_gitlab_issues() + logger.info(f"Found {len(issues)} issues") + + # Get a list of cards on the board + trello_cards = get_all_trello_cards() + logger.info(f"Found {len(trello_cards)} cards on the board") + + # Handle each issue + for issue in issues: + # Find the trello card id for this issue + trello_card_id = find_or_create_trello_issue_for(trello_cards, issue) + logger.info(f"GitLab Issue {issue.global_id} is Trello Card {trello_card_id}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 72a23f05829c42ede4a8263db658a021502d67a8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 1 Nov 2023 17:12:09 -0400 Subject: [PATCH 217/326] dont crash if win term is not installed --- install-windows.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/install-windows.sh b/install-windows.sh index 3dcff82..6e47674 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -28,6 +28,7 @@ mkdir -p ~/.ssh # Configure the shell ln -sf $EWCONFIG_ROOT/configs/shells/zsh/.zshrc ~/.zshrc ln -sf $EWCONFIG_ROOT/configs/shells/bash/.bashrc ~/.bashrc +mkdir -p $LOCALAPPDATA/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState ln -sf $EWCONFIG_ROOT/configs/windows-terminal/settings.json $LOCALAPPDATA/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json # Configure Git From 41963c2593e6d9fe799c6fba14647fe131c02cd6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 1 Nov 2023 17:15:26 -0400 Subject: [PATCH 218/326] Remove fake python from win10 machines --- install-windows.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/install-windows.sh b/install-windows.sh index 6e47674..a1b0c13 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -36,6 +36,10 @@ ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers || true ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap +# Remove Microsoft's fake python executables +rm $LOCALAPPDATA/Microsoft/WindowsApps/python.exe || true +rm $LOCALAPPDATA/Microsoft/WindowsApps/python3.exe || true + # Copy the global mailmap file once if [ ! -f ~/.config/git/config-fragments/global-mailmap.gitconfig ]; then cp $EWCONFIG_ROOT/configs/git/config-fragments/global-mailmap.gitconfig ~/.config/git/config-fragments/global-mailmap.gitconfig From f5d735b7a9d1b9c78198acf1d56d98da55981d3d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 1 Nov 2023 17:46:25 -0400 Subject: [PATCH 219/326] Allow falling back to an rsa key --- configs/ssh/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/ssh/config b/configs/ssh/config index 99754c1..ab276b1 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -3,7 +3,7 @@ Host * !*.github.com !github.com IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 IdentityFile %d/.ssh/id_ed25519 - # IdentityFile %d/.ssh/id_rsa + IdentityFile %d/.ssh/id_rsa VisualHostKey yes # Github SSH adapter for restricted networks From 1dce8badbd96468db25086978656b4b98df7ea30 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 1 Nov 2023 22:27:03 -0400 Subject: [PATCH 220/326] Add a script that pushes github issues to trello --- .gitignore | 1 + configs/scripts/github-to-trello | 163 +++++++++++++++++++++ configs/scripts/guru-sync-issues | 89 ++++------- python_modules/ewconfig/secret_manager.py | 24 +++ python_modules/ewconfig/trello/__init__.py | 8 + python_modules/ewconfig/trello/boards.py | 20 +++ python_modules/ewconfig/trello/cards.py | 80 ++++++++++ 7 files changed, 326 insertions(+), 59 deletions(-) create mode 100755 configs/scripts/github-to-trello create mode 100644 python_modules/ewconfig/secret_manager.py create mode 100644 python_modules/ewconfig/trello/__init__.py create mode 100644 python_modules/ewconfig/trello/boards.py create mode 100644 python_modules/ewconfig/trello/cards.py diff --git a/.gitignore b/.gitignore index 4fb0350..f4f5948 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +/secrets /configs/remmina __pycache__ \ No newline at end of file diff --git a/configs/scripts/github-to-trello b/configs/scripts/github-to-trello new file mode 100755 index 0000000..cbb19bc --- /dev/null +++ b/configs/scripts/github-to-trello @@ -0,0 +1,163 @@ +#! /usr/bin/env python3 + +# fmt:off +import sys +import os +from pathlib import Path +sys.path.append((Path(os.environ["EWCONFIG_ROOT"]) / "python_modules").as_posix()) +# fmt:on + +import argparse +import sys +import logging +import requests +from pathlib import Path +from dataclasses import dataclass, field +from typing import List, Optional, Dict, Any +from ewconfig.secret_manager import get_semi_secret_string +from ewconfig.trello import TRELLO_API_KEY, get_trello_api_token +from ewconfig.trello.cards import get_all_trello_cards, create_card, add_attachment +from ewconfig.trello.boards import PERSONAL_TASKS_BOARD + +logger = logging.getLogger(__name__) + +GITHUB_API_VERSION = "2022-11-28" +GITHUB_PAT = get_semi_secret_string("github_pat", namespace="trello-sync") +TRELLO_API_TOKEN = get_trello_api_token() + + +def get_all_issues() -> List[Dict[str, Any]]: + issues = [] + + # Get all issues assigned to me + response = requests.get( + "https://api.github.com/issues", + headers={ + "Authorization": f"token {GITHUB_PAT}", + "Accept": "application/vnd.github.raw+json", + "X-GitHub-Api-Version": GITHUB_API_VERSION, + }, + params={"state": "open", "per_page": 100}, + ) + response.raise_for_status() + issues.extend(response.json()) + + # Get all issues that mention me + response = requests.get( + "https://api.github.com/user/issues", + headers={ + "Authorization": f"token {GITHUB_PAT}", + "Accept": "application/vnd.github.raw+json", + "X-GitHub-Api-Version": GITHUB_API_VERSION, + }, + params={"state": "open", "per_page": 100, "filter": "mentioned"}, + ) + response.raise_for_status() + issues.extend(response.json()) + + # Get all issues that exist in my repos + response = requests.get( + "https://api.github.com/user/issues", + headers={ + "Authorization": f"token {GITHUB_PAT}", + "Accept": "application/vnd.github.raw+json", + "X-GitHub-Api-Version": GITHUB_API_VERSION, + }, + params={"state": "open", "per_page": 100, "filter": "repos"}, + ) + response.raise_for_status() + issues.extend(response.json()) + + # De-dupe issues + issues = list({issue["id"]: issue for issue in issues}.values()) + + return issues + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog="", description="") + ap.add_argument("--dry-run", help="Don't actually do anything", action="store_true") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Get a list of all issues assigned to me + my_issues = get_all_issues() + logger.info(f"Found {len(my_issues)} issues assigned to me") + + # Get all cards on the personal tasks board + trello_cards = get_all_trello_cards( + board_id=PERSONAL_TASKS_BOARD.id, + api_key=TRELLO_API_KEY, + api_token=TRELLO_API_TOKEN, + ) + logger.info(f"Found {len(trello_cards)} cards in Trello") + + # Handle each GitHub issue + for issue in my_issues: + # Ignore archived repos + if issue["repository"]["archived"]: + logger.info(f"Ignoring archived repo: {issue['repository']['full_name']}") + continue + + # Ignore anything by dependabot + if issue["user"]["login"] == "dependabot[bot]": + logger.debug(f"Ignoring dependabot issue: {issue['repository']['full_name']}#{issue['number']}") + continue + + # Search each card for anything that links to the github issue + for card in trello_cards: + if issue["html_url"] in card["desc"]: + logger.info( + f"Found GitHub Issue {issue['number']} in Trello Card {card['id']}" + ) + break + else: + logger.info( + f"Going to create trello card for GitHub Issue: [{issue['repository']['full_name']}] {issue['title']}" + ) + if not args.dry_run: + # Check if this is an issue or pr + is_pr = "pull_request" in issue + type_label = ( + PERSONAL_TASKS_BOARD.tags["Github: Pull Request"] + if is_pr + else PERSONAL_TASKS_BOARD.tags["Github: Issue"] + ) + + # Create a new trello card for this issue + card_id = create_card( + list_id=PERSONAL_TASKS_BOARD.lists["To Do"], + name=f"[{issue['repository']['full_name']}] {issue['title']}", + description=( + f"**GitHub Link:** [`{issue['repository']['full_name']}#{issue['number']}`]({issue['html_url']})\n\n" + f"**Author:** [`{issue['user']['login']}`]({issue['user']['html_url']})\n\n" + "---" + ), + label_ids=[type_label], + api_key=TRELLO_API_KEY, + api_token=TRELLO_API_TOKEN, + ) + add_attachment( + card_id=card_id, + api_key=TRELLO_API_KEY, + api_token=TRELLO_API_TOKEN, + url=issue["html_url"], + ) + logger.info( + f"Created Trello Card {card_id} for GitHub Issue {issue['repository']['full_name']}#{issue['number']}" + ) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/scripts/guru-sync-issues b/configs/scripts/guru-sync-issues index c968415..f16e889 100755 --- a/configs/scripts/guru-sync-issues +++ b/configs/scripts/guru-sync-issues @@ -1,4 +1,12 @@ #! /usr/bin/env python3 + +# fmt:off +import sys +import os +from pathlib import Path +sys.path.append((Path(os.environ["EWCONFIG_ROOT"]) / "python_modules").as_posix()) +# fmt:on + import argparse import sys import logging @@ -9,41 +17,19 @@ from pathlib import Path from typing import List, Optional, Dict, Any from enum import Enum, auto from datetime import datetime +from ewconfig.secret_manager import get_semi_secret_string +from ewconfig.trello import TRELLO_API_KEY, get_trello_api_token +from ewconfig.trello.cards import get_all_trello_cards, create_card +from ewconfig.trello.boards import PERSONAL_TASKS_BOARD logger = logging.getLogger(__name__) -GITLAB_PAT_FILE_PATH = Path("~/.config/guru-sync-issues/gitlab_pat.txt").expanduser() +GITLAB_PAT_FILE_PATH = get_semi_secret_string( + "guru_gitlab_pat", namespace="trello-sync" +) GITLAB_ENDPOINT = "http://gitlab.guru-domain.gurustudio.com/api/v4" MY_USER_ID = 64 -TRELLO_API_TOKEN_FILE_PATH = Path( - "~/.config/guru-sync-issues/trello_api_token.txt" -).expanduser() -TRELLO_API_KEY = "fba640a85f15c91e93e6b3f88e59489c" -TRELLO_BOARD = "tw3Cn3L6" -TRELLO_TODO_LIST = "6348a3ce5208f505b61d29bf" -TRELLO_LABELS = { - "GURU": "64e03ac77d27032282436d28" -} - -# Load the PAT -try: - with open(GITLAB_PAT_FILE_PATH) as f: - GITLAB_PAT = f.read().strip() -except FileNotFoundError: - logger.error( - f"Could not find GitLab PAT file at {GITLAB_PAT_FILE_PATH}. Please create it and try again." - ) - sys.exit(1) - -# Load Trello key -try: - with open(TRELLO_API_TOKEN_FILE_PATH) as f: - TRELLO_API_TOKEN = f.read().strip() -except FileNotFoundError: - logger.error( - f"Could not find Trello API key file at {TRELLO_API_TOKEN_FILE_PATH}. Please create it and try again." - ) - sys.exit(1) +TRELLO_API_TOKEN = get_trello_api_token() TrelloCardId = str @@ -101,19 +87,6 @@ def get_personal_gitlab_issues(user_id: int = MY_USER_ID) -> List[GitLabIssue]: return output -def get_all_trello_cards() -> List[Dict[str, Any]]: - # Get a list of cards on the board - response = requests.get( - f"https://api.trello.com/1/boards/{TRELLO_BOARD}/cards", - params={ - "key": TRELLO_API_KEY, - "token": TRELLO_API_TOKEN, - }, - ) - response.raise_for_status() - return response.json() - - def find_or_create_trello_issue_for( trello_cards: List[Dict[str, Any]], gitlab_issue: GitLabIssue ) -> TrelloCardId: @@ -141,26 +114,20 @@ def find_or_create_trello_issue_for( [ f"**Sync Metadata:** `{json.dumps({'ns': 'guru-gitlab', 'ids': [gitlab_issue.global_id]})}`", f"**GitLab Issue:** [`{gitlab_issue.reference_string}`]({gitlab_issue.web_url})\n", - "---" + "---", ] ) # Make a new card - response = requests.post( - "https://api.trello.com/1/cards", - params={ - "idList": TRELLO_TODO_LIST, - "name": gitlab_issue.title, - "desc": card_description, - "idLabels": ",".join([TRELLO_LABELS["GURU"]]), - "pos": "top", - "key": TRELLO_API_KEY, - "token": TRELLO_API_TOKEN, - }, + return create_card( + list_id=PERSONAL_TASKS_BOARD.lists["To Do"], + name=gitlab_issue.title, + description=card_description, + label_ids=[PERSONAL_TASKS_BOARD.tags["GURU"]], + position="top", + api_key=TRELLO_API_KEY, + api_token=TRELLO_API_TOKEN, ) - response.raise_for_status() - - return response.json()["id"] def main() -> int: @@ -183,7 +150,11 @@ def main() -> int: logger.info(f"Found {len(issues)} issues") # Get a list of cards on the board - trello_cards = get_all_trello_cards() + trello_cards = get_all_trello_cards( + board_id=PERSONAL_TASKS_BOARD.id, + api_key=TRELLO_API_KEY, + api_token=TRELLO_API_TOKEN, + ) logger.info(f"Found {len(trello_cards)} cards on the board") # Handle each issue diff --git a/python_modules/ewconfig/secret_manager.py b/python_modules/ewconfig/secret_manager.py new file mode 100644 index 0000000..e76ae72 --- /dev/null +++ b/python_modules/ewconfig/secret_manager.py @@ -0,0 +1,24 @@ +import logging +from pathlib import Path +from typing import Optional + +SEMI_SECRET_BASE_PATH = Path("~/.config/ewconfig/secrets/semi-secret").expanduser() + +logger = logging.getLogger(__name__) + +def get_semi_secret_string(name: str, namespace: Optional[str] = None) -> str: + logger.debug(f"Attempting to load secret: {name} (ns: {namespace})") + + # Construct file path + file = SEMI_SECRET_BASE_PATH + if namespace: + file = file / namespace + file = file / name + + # Make sure it exists + if not file.exists(): + raise FileNotFoundError(f"Could not load secret from: {file}") + + # Read the value + with open(file, "r") as f: + return f.read().strip() diff --git a/python_modules/ewconfig/trello/__init__.py b/python_modules/ewconfig/trello/__init__.py new file mode 100644 index 0000000..f22a8a7 --- /dev/null +++ b/python_modules/ewconfig/trello/__init__.py @@ -0,0 +1,8 @@ +from ..secret_manager import get_semi_secret_string + +TRELLO_API_KEY = "fba640a85f15c91e93e6b3f88e59489c" +"""Public api key to do things to personal Trello""" + + +def get_trello_api_token() -> str: + return get_semi_secret_string("trello_api_token") diff --git a/python_modules/ewconfig/trello/boards.py b/python_modules/ewconfig/trello/boards.py new file mode 100644 index 0000000..1c991fd --- /dev/null +++ b/python_modules/ewconfig/trello/boards.py @@ -0,0 +1,20 @@ +from dataclasses import dataclass +from typing import Dict + + +@dataclass +class TrelloBoardInfo: + id: str + lists: Dict[str, str] + tags: Dict[str, str] + + +PERSONAL_TASKS_BOARD = TrelloBoardInfo( + id="tw3Cn3L6", + lists={"To Do": "6348a3ce5208f505b61d29bf"}, + tags={ + "GURU": "64e03ac77d27032282436d28", + "Github: Issue": "64eb5d72fb694cd8f0ba7a8d", + "Github: Pull Request": "652d4b775f5c59a8e6308216", + }, +) diff --git a/python_modules/ewconfig/trello/cards.py b/python_modules/ewconfig/trello/cards.py new file mode 100644 index 0000000..d51e303 --- /dev/null +++ b/python_modules/ewconfig/trello/cards.py @@ -0,0 +1,80 @@ +import requests +import logging +from typing import Any, Dict, List, Optional + +logger = logging.getLogger(__name__) + + +def get_all_trello_cards( + board_id: str, api_key: str, api_token: str +) -> List[Dict[str, Any]]: + # Get a list of cards on the board + logger.debug(f"Getting all cards on board: {board_id}") + response = requests.get( + f"https://api.trello.com/1/boards/{board_id}/cards", + params={ + "key": api_key, + "token": api_token, + }, + ) + response.raise_for_status() + cards = response.json() + logger.debug(f"Found {len(cards)} cards on board: {board_id}") + return cards + + +def create_card( + list_id: str, + name: str, + api_key: str, + api_token: str, + description: Optional[str] = None, + label_ids: Optional[List[str]] = None, + position: str = "top", +) -> str: + logger.debug(f"Creating card: {name}") + + # Build out params + params = { + "idList": list_id, + "name": name, + "key": api_key, + "token": api_token, + "pos": position, + } + if description: + params["desc"] = description + if label_ids: + params["idLabels"] = ",".join(label_ids) + + # Make a new card + response = requests.post( + "https://api.trello.com/1/cards", + params=params, + ) + response.raise_for_status() + + # Get the new card's id + card_id = response.json()["id"] + + logger.debug(f"Created card: {card_id}") + return card_id + + +def add_attachment( + card_id: str, api_key: str, api_token: str, url: Optional[str] = None +) -> None: + logger.debug(f"Adding attachment to card: {card_id}") + params = { + "key": api_key, + "token": api_token, + } + if url: + params["url"] = url + + response = requests.post( + f"https://api.trello.com/1/cards/{card_id}/attachments", + params=params, + ) + response.raise_for_status() + logger.debug(f"Added attachment to card: {card_id}") From 3373a1d01c30d8974800a8444cd06fd709984db9 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 2 Nov 2023 09:35:35 -0400 Subject: [PATCH 221/326] fix bug --- configs/scripts/guru-sync-issues | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/configs/scripts/guru-sync-issues b/configs/scripts/guru-sync-issues index f16e889..b71d109 100755 --- a/configs/scripts/guru-sync-issues +++ b/configs/scripts/guru-sync-issues @@ -24,9 +24,7 @@ from ewconfig.trello.boards import PERSONAL_TASKS_BOARD logger = logging.getLogger(__name__) -GITLAB_PAT_FILE_PATH = get_semi_secret_string( - "guru_gitlab_pat", namespace="trello-sync" -) +GITLAB_PAT = get_semi_secret_string("guru_gitlab_pat", namespace="trello-sync") GITLAB_ENDPOINT = "http://gitlab.guru-domain.gurustudio.com/api/v4" MY_USER_ID = 64 TRELLO_API_TOKEN = get_trello_api_token() From 1a46f9796c4e233f3d600368b9675105ca3d3048 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 3 Nov 2023 10:24:35 -0400 Subject: [PATCH 222/326] various fixes --- configs/git/.gitconfig | 3 +- configs/scripts/github-to-trello | 13 ++++++ configs/scripts/guru-shell | 2 +- configs/scripts/guru-sync-issues | 68 ++++++++++++++++++++++++-------- 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 9e7aada..7b20dc5 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -23,7 +23,8 @@ branches = branch -a -l -vv overview = log --all --pretty=format:'%C(green)commit %C(yellow)%h%C(green) by %C(reset)%C(yellow)%aN %C(dim white)(%ar) %n%C(dim white)%S%n%B%n' lscommits = ! ( echo -e "Commits\tFile" && git log --pretty=format: --name-only | sed '/^$/d' | sort | uniq -c | sort -g -r ) | less - lsc = lscommits + lsc = lscommits + diff-against = diff --merge-base [filter "lfs"] clean = git-lfs clean -- %f diff --git a/configs/scripts/github-to-trello b/configs/scripts/github-to-trello index cbb19bc..6cf0063 100755 --- a/configs/scripts/github-to-trello +++ b/configs/scripts/github-to-trello @@ -67,6 +67,19 @@ def get_all_issues() -> List[Dict[str, Any]]: ) response.raise_for_status() issues.extend(response.json()) + + # Get all issues that I have made in other people's repos + response = requests.get( + "https://api.github.com/user/issues", + headers={ + "Authorization": f"token {GITHUB_PAT}", + "Accept": "application/vnd.github.raw+json", + "X-GitHub-Api-Version": GITHUB_API_VERSION, + }, + params={"state": "open", "per_page": 100, "filter": "subscribed"}, + ) + response.raise_for_status() + issues.extend(response.json()) # De-dupe issues issues = list({issue["id"]: issue for issue in issues}.values()) diff --git a/configs/scripts/guru-shell b/configs/scripts/guru-shell index bcf5560..ec4bd21 100755 --- a/configs/scripts/guru-shell +++ b/configs/scripts/guru-shell @@ -31,7 +31,7 @@ fi echo -n "Do you want to force debugging for all processes? (y/N)" read force_debug if [ "$force_debug" == "y" ]; then - export GURU_DEBUG=1 + export GURU_DEBUG=10 fi # Set PYTHONPATH based on the data we learned diff --git a/configs/scripts/guru-sync-issues b/configs/scripts/guru-sync-issues index b71d109..111b56a 100755 --- a/configs/scripts/guru-sync-issues +++ b/configs/scripts/guru-sync-issues @@ -42,6 +42,7 @@ class GitLabIssue: title: str issue_id: int global_id: int + kind: str state: IssueState created: datetime updated: datetime @@ -49,9 +50,21 @@ class GitLabIssue: reference_string: str due_date: Optional[datetime] = None + def get_fmt_id(self) -> str: + if self.kind == "merge_request": + return f"!{self.global_id}" + return f"#{self.global_id}" + + def list_contains_this(self, list_of_ids: List[str]) -> bool: + if self.kind == "issue" and self.global_id in list_of_ids: + return True + + return self.get_fmt_id() in [str(x) for x in list_of_ids] + def get_personal_gitlab_issues(user_id: int = MY_USER_ID) -> List[GitLabIssue]: # Make an API call + issues = [] response = requests.get( f"{GITLAB_ENDPOINT}/issues", params={ @@ -62,22 +75,36 @@ def get_personal_gitlab_issues(user_id: int = MY_USER_ID) -> List[GitLabIssue]: }, ) response.raise_for_status() + issues.extend(response.json()) + response = requests.get( + f"{GITLAB_ENDPOINT}/merge_requests", + params={ + "assignee_id": user_id, + "private_token": GITLAB_PAT, + "per_page": 100, + "scope": "all", + "state": "opened", + }, + ) + response.raise_for_status() + issues.extend(response.json()) # Parse the response output = [] - for issue in response.json(): + for issue in issues: output.append( GitLabIssue( title=issue["title"], issue_id=issue["iid"], global_id=issue["id"], + kind=issue.get("type", "merge_request").lower(), state=IssueState(issue["state"]), created=datetime.fromisoformat(issue["created_at"]), updated=datetime.fromisoformat(issue["updated_at"]), web_url=issue["web_url"], reference_string=issue["references"]["full"], due_date=datetime.fromisoformat(issue["due_date"]) - if issue["due_date"] + if issue.get("due_date") else None, ) ) @@ -86,7 +113,7 @@ def get_personal_gitlab_issues(user_id: int = MY_USER_ID) -> List[GitLabIssue]: def find_or_create_trello_issue_for( - trello_cards: List[Dict[str, Any]], gitlab_issue: GitLabIssue + trello_cards: List[Dict[str, Any]], gitlab_issue: GitLabIssue, dry_run: bool = False ) -> TrelloCardId: # Look for a card that matches the issue for card in trello_cards: @@ -100,8 +127,8 @@ def find_or_create_trello_issue_for( metadata = json.loads(desc_first_line.split("`")[1]) # Check if the card matches - if metadata.get("ns") == "guru-gitlab" and ( - gitlab_issue.global_id in metadata.get("ids", []) + if metadata.get("ns") == "guru-gitlab" and gitlab_issue.list_contains_this( + metadata.get("ids", []) ): print(card["labels"], card["idLabels"]) logger.info(f"Found matching card {card['id']}") @@ -110,28 +137,33 @@ def find_or_create_trello_issue_for( # Build the description card_description = "\n\n".join( [ - f"**Sync Metadata:** `{json.dumps({'ns': 'guru-gitlab', 'ids': [gitlab_issue.global_id]})}`", + f"**Sync Metadata:** `{json.dumps({'ns': 'guru-gitlab', 'ids': [gitlab_issue.get_fmt_id()]})}`", f"**GitLab Issue:** [`{gitlab_issue.reference_string}`]({gitlab_issue.web_url})\n", "---", ] ) # Make a new card - return create_card( - list_id=PERSONAL_TASKS_BOARD.lists["To Do"], - name=gitlab_issue.title, - description=card_description, - label_ids=[PERSONAL_TASKS_BOARD.tags["GURU"]], - position="top", - api_key=TRELLO_API_KEY, - api_token=TRELLO_API_TOKEN, - ) + if not dry_run: + return create_card( + list_id=PERSONAL_TASKS_BOARD.lists["To Do"], + name=gitlab_issue.title, + description=card_description, + label_ids=[PERSONAL_TASKS_BOARD.tags["GURU"]], + position="top", + api_key=TRELLO_API_KEY, + api_token=TRELLO_API_TOKEN, + ) + else: + return "dry-run" def main() -> int: # Handle program arguments ap = argparse.ArgumentParser(description="Syncs issues from GitLab to Trello") - + ap.add_argument( + "--dry-run", help="Don't actually make any changes", action="store_true" + ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) @@ -158,7 +190,9 @@ def main() -> int: # Handle each issue for issue in issues: # Find the trello card id for this issue - trello_card_id = find_or_create_trello_issue_for(trello_cards, issue) + trello_card_id = find_or_create_trello_issue_for( + trello_cards, issue, dry_run=args.dry_run + ) logger.info(f"GitLab Issue {issue.global_id} is Trello Card {trello_card_id}") return 0 From da7e0ba865d7dee76c1c7fe3f7efc8a4c6933ce9 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 3 Nov 2023 10:55:48 -0400 Subject: [PATCH 223/326] fix name --- configs/scripts/guru-sync-issues | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/scripts/guru-sync-issues b/configs/scripts/guru-sync-issues index 111b56a..33216e8 100755 --- a/configs/scripts/guru-sync-issues +++ b/configs/scripts/guru-sync-issues @@ -135,10 +135,11 @@ def find_or_create_trello_issue_for( return card["id"] # Build the description + issue_kind = " ".join([part.capitalize() for part in gitlab_issue.kind.split("_")]) card_description = "\n\n".join( [ f"**Sync Metadata:** `{json.dumps({'ns': 'guru-gitlab', 'ids': [gitlab_issue.get_fmt_id()]})}`", - f"**GitLab Issue:** [`{gitlab_issue.reference_string}`]({gitlab_issue.web_url})\n", + f"**GitLab {issue_kind}:** [`{gitlab_issue.reference_string}`]({gitlab_issue.web_url})\n", "---", ] ) From 12403eccf9ff4b503b04eb6863146813a02fbb5e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 6 Nov 2023 15:13:17 -0500 Subject: [PATCH 224/326] basic basejump script --- configs/scripts/basejump | 37 +++++++++++++++++ configs/scripts/basejump-fetch | 58 ++++++++++++++++++++++++++ configs/scripts/basejump-init | 75 ++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100755 configs/scripts/basejump create mode 100755 configs/scripts/basejump-fetch create mode 100755 configs/scripts/basejump-init diff --git a/configs/scripts/basejump b/configs/scripts/basejump new file mode 100755 index 0000000..9f07900 --- /dev/null +++ b/configs/scripts/basejump @@ -0,0 +1,37 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import subprocess + + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog="basejump") + ap.add_argument( + "subcommand", help="The subcommand to run", choices=["init", "fetch"] + ) + ap.add_argument("arguments", nargs=argparse.REMAINDER) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Execute the appropriate subcommand + real_command_name = f"basejump-{args.subcommand}" + try: + return subprocess.run([real_command_name] + args.arguments).returncode + except FileNotFoundError: + logger.error(f"Unknown subcommand: {args.subcommand}") + logger.error(f"Could not find `{real_command_name}` in $PATH") + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/scripts/basejump-fetch b/configs/scripts/basejump-fetch new file mode 100755 index 0000000..ce050b1 --- /dev/null +++ b/configs/scripts/basejump-fetch @@ -0,0 +1,58 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import json +import subprocess +import os +from pathlib import Path + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="basejump fetch", description="Fetches all changes for a whole codebase" + ) + ap.add_argument("name", help="The name of the codebase") + ap.add_argument("--pull", help="Perform a full pull", action="store_true") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Ensure that the basejump config dir exists + bj_config_dir = Path.home() / ".config" / "basejump" + bj_config_dir.mkdir(parents=True, exist_ok=True) + + # Read the codebase config + codebase_config_path = bj_config_dir / f"{args.name}.codebase.json" + if not codebase_config_path.exists(): + logger.error(f"Codebase `{args.name}` does not exist") + return 1 + config = json.loads(codebase_config_path.read_text()) + + # Handle each repository + for repo in config["repos"]: + logger.info(f"Fetching {repo['path']}") + + # If we are in pull mode, do a git pull + if args.pull: + subprocess.run(["git", "pull"], cwd=repo["path"]) + + # Otherwise fetch all + else: + subprocess.run(["git", "fetch", "--all"], cwd=repo["path"]) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/scripts/basejump-init b/configs/scripts/basejump-init new file mode 100755 index 0000000..0013ea7 --- /dev/null +++ b/configs/scripts/basejump-init @@ -0,0 +1,75 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import json +import subprocess +import os +from pathlib import Path + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="basejump init", description="Creates a new basejump codebase" + ) + ap.add_argument("name", help="The name of the codebase") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Ensure that the basejump config dir exists + bj_config_dir = Path.home() / ".config" / "basejump" + bj_config_dir.mkdir(parents=True, exist_ok=True) + + # Create a new codebase definition + codebase_config_path = bj_config_dir / f"{args.name}.codebase.json" + + # If the path already exists, abort + if codebase_config_path.exists(): + logger.error(f"Codebase `{args.name}` already exists") + logger.info(f"Config file at: {codebase_config_path}") + return 1 + + # Create a template codebase config + template_config = { + "name": args.name, + "repos": [ + { + "path": "/tmp/example", + "upstream": "https://github.com/octocat/Hello-World", + } + ], + } + + # Write the template config to disk + codebase_config_path.write_text(json.dumps(template_config, indent=4)) + + # Open $EDITOR (or vim) to edit the config + subprocess.run([os.environ.get("EDITOR", "vim"), str(codebase_config_path)]) + + # Iterate through every repo and clone it + config = json.loads(codebase_config_path.read_text()) + for repo in config["repos"]: + if Path(repo["path"]).exists(): + logger.info(f"Skipping {repo['path']}, already exists") + continue + + # Do a clone + logger.info(f"Cloning {repo['upstream']} into {repo['path']}") + subprocess.run(["git", "clone", repo["upstream"], repo["path"]]) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 26a29da91428a6fd7ce4ee81edbb8ae5f8e3554f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 7 Nov 2023 12:21:39 -0500 Subject: [PATCH 225/326] ufw stuff --- configs/scripts/ufw-del | 50 ++++++++++++++++++ configs/scripts/ufw-gen | 95 +++++++++++++++++++++++++++++++++++ configs/shells/bash/macros.sh | 1 + install-linux.sh | 2 +- 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100755 configs/scripts/ufw-del create mode 100755 configs/scripts/ufw-gen diff --git a/configs/scripts/ufw-del b/configs/scripts/ufw-del new file mode 100755 index 0000000..f6dd513 --- /dev/null +++ b/configs/scripts/ufw-del @@ -0,0 +1,50 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import subprocess + +logger = logging.getLogger(__name__) + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog='ufw-del', description='Delete UFW rules by their comment') + ap.add_argument('comment', help='Comment to delete') + ap.add_argument("--dry-run", help="Don't actually delete the rules", action="store_true") + ap.add_argument('-v', '--verbose', help='Enable verbose logging', action='store_true') + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format='%(levelname)s: %(message)s', + ) + + # Call ufw to get a list of rules + logger.info('Getting list of rules...') + rules = subprocess.run(['sudo', 'ufw', 'status', 'numbered'], capture_output=True, text=True).stdout.split('\n') + rules = [rule for rule in rules if rule.startswith('[')] + logger.info(f'Found {len(rules)} rules') + + # Reshape the rules list to be (number, line) tuples + rules = [(int(rule.split('[')[1].split(']')[0].strip()), rule) for rule in rules] + + # Sort descending by rule number + rules.sort(key=lambda x: x[0], reverse=True) + + # Delete rules with the specified comment + for rule_num, rule in rules: + if "#" in rule: + comment = rule.split('#')[1].strip() + if comment == args.comment: + rule_id = rule.split("]")[0].strip('[').strip() + logger.info(f'Deleting rule {rule_id}...') + + if not args.dry_run: + subprocess.run(['sudo', 'ufw', 'delete', rule_id]) + + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file diff --git a/configs/scripts/ufw-gen b/configs/scripts/ufw-gen new file mode 100755 index 0000000..700bd08 --- /dev/null +++ b/configs/scripts/ufw-gen @@ -0,0 +1,95 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import subprocess + +logger = logging.getLogger(__name__) + +PROFILES = { + "minecraft": { + "comment": "Minecraft Server", + "ports": [(25565, "tcp"), (25565, "udp")], + }, + "unturned": { + "comment": "Unturned Server", + "ports": [(27015, "tcp"), (27015, "udp"), (27016, "tcp"), (27016, "udp")], + }, + "zola": { + "comment": "Zola", + "ports": [(1111, "tcp")], + }, +} + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="ufw-gen", description="Generate UFW allow commands" + ) + ap.add_argument( + "profile", + help="Profile to generate UFW allow commands for", + choices=PROFILES.keys(), + ) + ap.add_argument("--from", help="Source IP address", default="any", dest="source") + ap.add_argument("--to", help="Destination IP address", default="any", dest="dest") + ap.add_argument( + "--no-sudo", help="Don't prefix commands with sudo", action="store_true" + ) + ap.add_argument( + "--dry-run", help="Generate UFW commands in dry-run mode", action="store_true" + ) + ap.add_argument( + "--execute", "-x", help="Execute generated UFW commands", action="store_true" + ) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Generate UFW allow commands + profile = PROFILES[args.profile] + for port, proto in profile["ports"]: + sudo_str = "" if args.no_sudo else "sudo " + dry_run_str = "--dry-run" if args.dry_run else "" + + # Generate the command + command = ["sudo", "ufw"] if not args.no_sudo else ["ufw"] + if args.dry_run: + command.append("--dry-run") + command.extend( + [ + "allow", + "from", + args.source, + "to", + args.dest, + "port", + str(port), + "proto", + proto, + "comment", + profile["comment"], + ] + ) + + # Run + print(" ".join(command)) + if args.execute: + result = subprocess.run(command).returncode + if result != 0: + logger.error("Failed to run command: %s", command) + return result + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 2275492..dc932a4 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -21,6 +21,7 @@ alias yk-totp="ykman oath accounts code" alias flush-dns-cache="sudo systemd-resolve --flush-caches" alias which-ls="ls -la $(which ls)" alias rdns="dig +short -x" +alias ufw-status="sudo ufw status numbered" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" diff --git a/install-linux.sh b/install-linux.sh index 1a63f25..50a163f 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -115,7 +115,7 @@ set +x # If ~/.config/git/config-fragments/personal-info.gitconfig does not exist if [ ! -f ~/.config/git/config-fragments/personal-info.gitconfig ]; then # Ask if the user wants to install personal GIT config - echo "Do you want to install the personal GIT config? (y/n)" + echo -n "Do you want to install the personal GIT config? (y/n) " read -r install_git_config if [ "$install_git_config" = "y" ]; then ln -sf $EWCONFIG_ROOT/configs/git/config-fragments/personal-info.gitconfig ~/.config/git/config-fragments/personal-info.gitconfig From f171acd46acc523ce0a7f53a128ef947c8559922 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 7 Nov 2023 13:23:22 -0500 Subject: [PATCH 226/326] Add a command to fix up bad branches --- configs/git/.gitconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 7b20dc5..c341b18 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -25,6 +25,7 @@ lscommits = ! ( echo -e "Commits\tFile" && git log --pretty=format: --name-only | sed '/^$/d' | sort | uniq -c | sort -g -r ) | less lsc = lscommits diff-against = diff --merge-base + fix-recreated-branch = reset --hard @{u} [filter "lfs"] clean = git-lfs clean -- %f From 9deeb205b5296161851cd5fc1c56e272768cf8c4 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 10:08:08 -0500 Subject: [PATCH 227/326] Add support for line search over SSH --- configs/shells/zsh/autocomplete.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/shells/zsh/autocomplete.sh b/configs/shells/zsh/autocomplete.sh index dbcb70d..cc501ed 100644 --- a/configs/shells/zsh/autocomplete.sh +++ b/configs/shells/zsh/autocomplete.sh @@ -41,3 +41,6 @@ zle -N up-line-or-beginning-search zle -N down-line-or-beginning-search bindkey "^[[A" up-line-or-beginning-search # Up bindkey "^[[B" down-line-or-beginning-search # Down +bindkey "^[OA" up-line-or-beginning-search # Up over SSH connection +bindkey "^[OB" down-line-or-beginning-search # Down over SSH connection + From 66f6195ee518f2c368fb1cf75794fbb3248a0932 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 11:43:06 -0500 Subject: [PATCH 228/326] Pull TG4X config into config tree --- configs/scripts/qmk-helper | 157 ++++++++++++++++++++++++++++ keyboards/qmk/keymaps/tg4x/config.h | 5 + keyboards/qmk/keymaps/tg4x/keymap.c | 47 +++++++++ keyboards/qmk/keymaps/tg4x/rules.mk | 8 ++ 4 files changed, 217 insertions(+) create mode 100755 configs/scripts/qmk-helper create mode 100644 keyboards/qmk/keymaps/tg4x/config.h create mode 100644 keyboards/qmk/keymaps/tg4x/keymap.c create mode 100644 keyboards/qmk/keymaps/tg4x/rules.mk diff --git a/configs/scripts/qmk-helper b/configs/scripts/qmk-helper new file mode 100755 index 0000000..cc4301d --- /dev/null +++ b/configs/scripts/qmk-helper @@ -0,0 +1,157 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import subprocess +import shutil +import os +from pathlib import Path + +logger = logging.getLogger(__name__) + +QMK_REPOSITORY = "https://github.com/qmk/qmk_firmware" +QMK_PINNED_COMMIT = "daabe2d8c5eab9d9d605f8e079dfae82d2b06a8d" +QMK_CLONE_PATH = Path("~/src/qmk_firmware").expanduser() +QMK_USERNAME = "ewpratten" +LOCAL_KEYMAPS_ROOT = Path(os.environ["EWCONFIG_ROOT"]) / "keyboards" / "qmk" / "keymaps" + + +def check_prerequisite_tools() -> bool: + # Ensure we have git + if shutil.which("git") is None: + logger.error("git is not installed") + return False + + # Ensure we have make + if shutil.which("make") is None: + logger.error("make is not installed") + return False + + # Ensure we have qmk + if shutil.which("qmk") is None: + logger.error("qmk is not installed") + return False + + # OK + return True + + +def refresh_qmk_repo(): + # If the repo doesn't exist, clone it + if not QMK_CLONE_PATH.exists(): + logger.info("Cloning QMK repository") + QMK_CLONE_PATH.parent.mkdir(parents=True, exist_ok=True) + subprocess.run( + ["git", "clone", QMK_REPOSITORY, QMK_CLONE_PATH], + check=True, + ) + + # Drop any local changes + logger.info("Dropping local changes") + subprocess.run( + ["git", "reset", "--hard"], + check=True, + cwd=QMK_CLONE_PATH, + ) + + # Pull the latest changes and then checkout the pinned commit + logger.info("Updating QMK repository") + subprocess.run( + ["git", "fetch", "--all"], + check=True, + cwd=QMK_CLONE_PATH, + ) + subprocess.run( + ["git", "checkout", QMK_PINNED_COMMIT], + check=True, + cwd=QMK_CLONE_PATH, + ) + + # Update submodules + logger.info("Updating QMK submodules") + subprocess.run( + ["git", "submodule", "update", "--init", "--recursive"], + check=True, + cwd=QMK_CLONE_PATH, + ) + + +def copy_keymap(keyboard: str): + # Build the path that this keymap should be copied to + KEYMAP_PATH = QMK_CLONE_PATH / "keyboards" / keyboard / "keymaps" / QMK_USERNAME + + # If the keymap already exists, delete it + if KEYMAP_PATH.exists(): + logger.info("Removing existing keymap") + shutil.rmtree(KEYMAP_PATH) + + # Copy the keymap + logger.info(f"Copying keymap to: {KEYMAP_PATH}") + shutil.copytree(LOCAL_KEYMAPS_ROOT / keyboard, KEYMAP_PATH) + + +def build_keymap(keyboard: str): + # Build the keymap + logger.info(f"Building keymap: {keyboard}") + subprocess.run( + ["make", keyboard + ":" + QMK_USERNAME], + check=True, + cwd=QMK_CLONE_PATH, + ) + + +def flash_keymap(keyboard: str, flash_mode: str): + # Flash the keymap + logger.info(f"Flashing keymap: {keyboard} ({flash_mode})") + subprocess.run( + ["qmk", "flash", "-kb", keyboard, "-km", QMK_USERNAME, "-bl", flash_mode], + check=True, + cwd=QMK_CLONE_PATH, + ) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="qmk-helper", description="Utility for flashing QMK boards" + ) + ap.add_argument("mode", choices=["build", "flash"], help="Mode to run in") + ap.add_argument( + "keyboard", + help="Keyboard to build/flash", + choices=["tg4x"], + ) + ap.add_argument("--flash-mode", "-f", help="Flash mode to use", default="flash") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Check for prerequisite tools + if not check_prerequisite_tools(): + return 1 + logger.info("Prerequisite tools found") + + # Refresh the QMK repository + refresh_qmk_repo() + + # Copy the keymap + copy_keymap(args.keyboard) + + # Handle the modes + if args.mode == "build": + build_keymap(args.keyboard) + elif args.mode == "flash": + flash_keymap(args.keyboard, args.flash_mode) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/keyboards/qmk/keymaps/tg4x/config.h b/keyboards/qmk/keymaps/tg4x/config.h new file mode 100644 index 0000000..f779a3b --- /dev/null +++ b/keyboards/qmk/keymaps/tg4x/config.h @@ -0,0 +1,5 @@ +#pragma once + +// Threshold for things considered a "tap" +#define TAPPING_TERM 300 + diff --git a/keyboards/qmk/keymaps/tg4x/keymap.c b/keyboards/qmk/keymaps/tg4x/keymap.c new file mode 100644 index 0000000..2d74274 --- /dev/null +++ b/keyboards/qmk/keymaps/tg4x/keymap.c @@ -0,0 +1,47 @@ +// Pull in the QMK lib +#include QMK_KEYBOARD_H + +/* Trickery to make VSCode happy */ +#include +#define _____ KC_NO +#define _PASS KC_TRNS + +/* Layer Definitions */ +// clang-format off +enum tg4x_layers { + QWERTY, + NUMERIC, + ACTIONS, +}; +// clang-format on + +/* Layers */ +// clang-format off +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + // QWERTY + [QWERTY] = LAYOUT( + KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, KC_BSPC, + KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_RSFT, MO(NUMERIC), + KC_LCTL, KC_LALT, KC_LGUI, KC_SPACE, KC_SPACE, MO(ACTIONS), _____, _____, _____ + ), + + // NUMERIC + [NUMERIC] = LAYOUT( + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, + KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, + _PASS, _____, _____, _____, _____, KC_QUOTE, KC_SLSH, KC_LBRC, KC_RBRC, KC_BSLS, _____, _____, + _PASS, _PASS, _PASS, KC_SPACE, KC_SPACE, _____, _____, _____, _____ + ), + + // ACTIONS + [ACTIONS] = LAYOUT( + _____, KC_VOLD, KC_VOLU, KC_MUTE, _____, _____, _____, KC_PGUP, _____, KC_PGDN, KC_PSCR, KC_SCRL, KC_PAUS, + KC_CAPS, KC_MPRV, KC_MPLY, KC_MNXT, _____, _____, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_INS, _____, + _PASS, RGB_TOG, _____, _____, _____, KC_HOME, KC_END, _____, _____, _____, _PASS, _____, + _PASS, _PASS, _PASS, KC_SPACE, KC_SPACE, _____, _____, _____, _____ + ), + +}; +// clang-format on diff --git a/keyboards/qmk/keymaps/tg4x/rules.mk b/keyboards/qmk/keymaps/tg4x/rules.mk new file mode 100644 index 0000000..0b15970 --- /dev/null +++ b/keyboards/qmk/keymaps/tg4x/rules.mk @@ -0,0 +1,8 @@ +# Override the default bootloader since I am using a non-standard MCU +BOOTLOADER = qmk-dfu + +# Enable bootloader keys +BOOTMAGIC_ENABLE = yes + +# Enable Unicode +UNICODE_ENABLE = yes \ No newline at end of file From 371d753f1612e0d6e2817b6bb92f97fddd531813 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 11:47:47 -0500 Subject: [PATCH 229/326] Reorg --- .../gnome/gnome-terminal-settings.sh | 9 ++++----- configs/shells/bash/.bashrc | 2 +- configs/shells/zsh/.zshrc | 2 +- install-linux.sh | 3 ++- {configs/scripts => scripts}/aspath | 0 {configs/scripts => scripts}/basejump | 0 {configs/scripts => scripts}/basejump-fetch | 0 {configs/scripts => scripts}/basejump-init | 0 {configs/scripts => scripts}/catto | 0 .../scripts => scripts}/configure-gnome-remote-desktop | 0 {configs/scripts => scripts}/deadline-read-options | 0 {configs/scripts => scripts}/ewp-sendmail | 0 {configs/scripts => scripts}/fetch-steamdeck-screenshots | 0 {configs/scripts => scripts}/git-authors-multirepo | 0 {configs/scripts => scripts}/github-to-trello | 0 {configs/scripts => scripts}/guru-shell | 0 {configs/scripts => scripts}/guru-sync-issues | 0 {configs/scripts => scripts}/guru-vpn | 0 {configs/scripts => scripts}/houdini-tool | 0 {configs/scripts => scripts}/hython-latest | 0 {configs/scripts => scripts}/install-nvim-appimage | 0 {configs/scripts => scripts}/install-nvim-from-source | 0 {configs/scripts => scripts}/qmk-helper | 0 {configs/scripts => scripts}/run-logid | 0 {configs/scripts => scripts}/scp-make-upload-acl | 0 {configs/scripts => scripts}/show-pythonpath | 0 {configs/scripts => scripts}/ufw-del | 0 {configs/scripts => scripts}/ufw-gen | 0 {configs/scripts => scripts}/usdnc-to-usd | 0 {configs/scripts => scripts}/video_trimmer | 0 {configs/scripts => scripts}/wg-genzone | 0 {configs/scripts => scripts}/wg-handshakes | 0 32 files changed, 8 insertions(+), 8 deletions(-) rename helpers/configure-gnome.sh => configs/gnome/gnome-terminal-settings.sh (58%) rename {configs/scripts => scripts}/aspath (100%) rename {configs/scripts => scripts}/basejump (100%) rename {configs/scripts => scripts}/basejump-fetch (100%) rename {configs/scripts => scripts}/basejump-init (100%) rename {configs/scripts => scripts}/catto (100%) rename {configs/scripts => scripts}/configure-gnome-remote-desktop (100%) rename {configs/scripts => scripts}/deadline-read-options (100%) rename {configs/scripts => scripts}/ewp-sendmail (100%) rename {configs/scripts => scripts}/fetch-steamdeck-screenshots (100%) rename {configs/scripts => scripts}/git-authors-multirepo (100%) rename {configs/scripts => scripts}/github-to-trello (100%) rename {configs/scripts => scripts}/guru-shell (100%) rename {configs/scripts => scripts}/guru-sync-issues (100%) rename {configs/scripts => scripts}/guru-vpn (100%) rename {configs/scripts => scripts}/houdini-tool (100%) rename {configs/scripts => scripts}/hython-latest (100%) rename {configs/scripts => scripts}/install-nvim-appimage (100%) rename {configs/scripts => scripts}/install-nvim-from-source (100%) rename {configs/scripts => scripts}/qmk-helper (100%) rename {configs/scripts => scripts}/run-logid (100%) rename {configs/scripts => scripts}/scp-make-upload-acl (100%) rename {configs/scripts => scripts}/show-pythonpath (100%) rename {configs/scripts => scripts}/ufw-del (100%) rename {configs/scripts => scripts}/ufw-gen (100%) rename {configs/scripts => scripts}/usdnc-to-usd (100%) rename {configs/scripts => scripts}/video_trimmer (100%) rename {configs/scripts => scripts}/wg-genzone (100%) rename {configs/scripts => scripts}/wg-handshakes (100%) diff --git a/helpers/configure-gnome.sh b/configs/gnome/gnome-terminal-settings.sh similarity index 58% rename from helpers/configure-gnome.sh rename to configs/gnome/gnome-terminal-settings.sh index 0faa1ff..51b0601 100644 --- a/helpers/configure-gnome.sh +++ b/configs/gnome/gnome-terminal-settings.sh @@ -1,6 +1,9 @@ #! /bin/sh set -e +# Get the path to this script +SCRIPT_PATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + # Check if dconf is available if ! command -v dconf >/dev/null 2>&1; then echo "dconf is not installed, skipping GNOME configuration" @@ -9,8 +12,4 @@ fi # Configure gnome-terminal echo "Writing gnome-terminal settings..." -dconf load "/org/gnome/terminal/" < configs/gnome/terminal/terminal.dconf - -# Configure GNOME itself -echo "Writing GNOME settings..." -sh ./configs/gnome/desktop-settings.sh \ No newline at end of file +dconf load "/org/gnome/terminal/" < $SCRIPT_PATH/terminal/terminal.dconf diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 342546e..44a9343 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -9,7 +9,7 @@ export EWCONFIG_ROOT="$HOME/.config/ewconfig" # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" -export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" +export PATH="$EWCONFIG_ROOT/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" # A basic prompt to display user@host dir sign diff --git a/configs/shells/zsh/.zshrc b/configs/shells/zsh/.zshrc index 8e5f39f..26de500 100644 --- a/configs/shells/zsh/.zshrc +++ b/configs/shells/zsh/.zshrc @@ -18,7 +18,7 @@ fi # I always want my ~/bin to be in my PATH export PATH="$HOME/bin:$PATH" -export PATH="$EWCONFIG_ROOT/configs/scripts:$PATH" +export PATH="$EWCONFIG_ROOT/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" # Configure a sane default editor diff --git a/install-linux.sh b/install-linux.sh index 50a163f..10b1ad6 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -131,7 +131,8 @@ if [ -d ~/.config/blender/3.6 ]; then ln -sf $EWCONFIG_ROOT/configs/blender/3.x/ # -- Finalization -- # On systems that need it, configure Gnome -sh ./helpers/configure-gnome.sh +sh ./configs/gnome/gnome-terminal-settings.sh +sh ./configs/gnome/desktop-settings.sh # Attempt to force a termux settings reload on Android devices termux-reload-settings || true diff --git a/configs/scripts/aspath b/scripts/aspath similarity index 100% rename from configs/scripts/aspath rename to scripts/aspath diff --git a/configs/scripts/basejump b/scripts/basejump similarity index 100% rename from configs/scripts/basejump rename to scripts/basejump diff --git a/configs/scripts/basejump-fetch b/scripts/basejump-fetch similarity index 100% rename from configs/scripts/basejump-fetch rename to scripts/basejump-fetch diff --git a/configs/scripts/basejump-init b/scripts/basejump-init similarity index 100% rename from configs/scripts/basejump-init rename to scripts/basejump-init diff --git a/configs/scripts/catto b/scripts/catto similarity index 100% rename from configs/scripts/catto rename to scripts/catto diff --git a/configs/scripts/configure-gnome-remote-desktop b/scripts/configure-gnome-remote-desktop similarity index 100% rename from configs/scripts/configure-gnome-remote-desktop rename to scripts/configure-gnome-remote-desktop diff --git a/configs/scripts/deadline-read-options b/scripts/deadline-read-options similarity index 100% rename from configs/scripts/deadline-read-options rename to scripts/deadline-read-options diff --git a/configs/scripts/ewp-sendmail b/scripts/ewp-sendmail similarity index 100% rename from configs/scripts/ewp-sendmail rename to scripts/ewp-sendmail diff --git a/configs/scripts/fetch-steamdeck-screenshots b/scripts/fetch-steamdeck-screenshots similarity index 100% rename from configs/scripts/fetch-steamdeck-screenshots rename to scripts/fetch-steamdeck-screenshots diff --git a/configs/scripts/git-authors-multirepo b/scripts/git-authors-multirepo similarity index 100% rename from configs/scripts/git-authors-multirepo rename to scripts/git-authors-multirepo diff --git a/configs/scripts/github-to-trello b/scripts/github-to-trello similarity index 100% rename from configs/scripts/github-to-trello rename to scripts/github-to-trello diff --git a/configs/scripts/guru-shell b/scripts/guru-shell similarity index 100% rename from configs/scripts/guru-shell rename to scripts/guru-shell diff --git a/configs/scripts/guru-sync-issues b/scripts/guru-sync-issues similarity index 100% rename from configs/scripts/guru-sync-issues rename to scripts/guru-sync-issues diff --git a/configs/scripts/guru-vpn b/scripts/guru-vpn similarity index 100% rename from configs/scripts/guru-vpn rename to scripts/guru-vpn diff --git a/configs/scripts/houdini-tool b/scripts/houdini-tool similarity index 100% rename from configs/scripts/houdini-tool rename to scripts/houdini-tool diff --git a/configs/scripts/hython-latest b/scripts/hython-latest similarity index 100% rename from configs/scripts/hython-latest rename to scripts/hython-latest diff --git a/configs/scripts/install-nvim-appimage b/scripts/install-nvim-appimage similarity index 100% rename from configs/scripts/install-nvim-appimage rename to scripts/install-nvim-appimage diff --git a/configs/scripts/install-nvim-from-source b/scripts/install-nvim-from-source similarity index 100% rename from configs/scripts/install-nvim-from-source rename to scripts/install-nvim-from-source diff --git a/configs/scripts/qmk-helper b/scripts/qmk-helper similarity index 100% rename from configs/scripts/qmk-helper rename to scripts/qmk-helper diff --git a/configs/scripts/run-logid b/scripts/run-logid similarity index 100% rename from configs/scripts/run-logid rename to scripts/run-logid diff --git a/configs/scripts/scp-make-upload-acl b/scripts/scp-make-upload-acl similarity index 100% rename from configs/scripts/scp-make-upload-acl rename to scripts/scp-make-upload-acl diff --git a/configs/scripts/show-pythonpath b/scripts/show-pythonpath similarity index 100% rename from configs/scripts/show-pythonpath rename to scripts/show-pythonpath diff --git a/configs/scripts/ufw-del b/scripts/ufw-del similarity index 100% rename from configs/scripts/ufw-del rename to scripts/ufw-del diff --git a/configs/scripts/ufw-gen b/scripts/ufw-gen similarity index 100% rename from configs/scripts/ufw-gen rename to scripts/ufw-gen diff --git a/configs/scripts/usdnc-to-usd b/scripts/usdnc-to-usd similarity index 100% rename from configs/scripts/usdnc-to-usd rename to scripts/usdnc-to-usd diff --git a/configs/scripts/video_trimmer b/scripts/video_trimmer similarity index 100% rename from configs/scripts/video_trimmer rename to scripts/video_trimmer diff --git a/configs/scripts/wg-genzone b/scripts/wg-genzone similarity index 100% rename from configs/scripts/wg-genzone rename to scripts/wg-genzone diff --git a/configs/scripts/wg-handshakes b/scripts/wg-handshakes similarity index 100% rename from configs/scripts/wg-handshakes rename to scripts/wg-handshakes From f91a1b6c056c9620e1f2b2f247195044d3df0df6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 11:48:34 -0500 Subject: [PATCH 230/326] fix modes --- install-linux.sh | 2 +- install-windows.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install-linux.sh b/install-linux.sh index 10b1ad6..8293c72 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -14,7 +14,7 @@ if type -p git > /dev/null; then fi # Make sure scripts are all executable -chmod +x $EWCONFIG_ROOT/configs/scripts/* +chmod +x $EWCONFIG_ROOT/scripts/* chmod +x $EWCONFIG_ROOT/configs/nautilus/scripts/* # -- Directory Setup -- diff --git a/install-windows.sh b/install-windows.sh index a1b0c13..1332d1e 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -7,7 +7,7 @@ echo "Syncing git submodules..." git submodule update --init --recursive # Make sure scripts are all executable -chmod +x $EWCONFIG_ROOT/configs/scripts/* +chmod +x $EWCONFIG_ROOT/scripts/* chmod +x $EWCONFIG_ROOT/configs/nautilus/scripts/* # -- Directory Setup -- From 0b68ee795a2ee4976795b3b8f11811ea684bf6a7 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 12:45:44 -0500 Subject: [PATCH 231/326] Clean out unicode support (for now) --- keyboards/qmk/keymaps/tg4x/config.h | 3 +-- keyboards/qmk/keymaps/tg4x/rules.mk | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/keyboards/qmk/keymaps/tg4x/config.h b/keyboards/qmk/keymaps/tg4x/config.h index f779a3b..f6abda1 100644 --- a/keyboards/qmk/keymaps/tg4x/config.h +++ b/keyboards/qmk/keymaps/tg4x/config.h @@ -1,5 +1,4 @@ #pragma once // Threshold for things considered a "tap" -#define TAPPING_TERM 300 - +#define TAPPING_TERM 300 \ No newline at end of file diff --git a/keyboards/qmk/keymaps/tg4x/rules.mk b/keyboards/qmk/keymaps/tg4x/rules.mk index 0b15970..f37bec0 100644 --- a/keyboards/qmk/keymaps/tg4x/rules.mk +++ b/keyboards/qmk/keymaps/tg4x/rules.mk @@ -3,6 +3,3 @@ BOOTLOADER = qmk-dfu # Enable bootloader keys BOOTMAGIC_ENABLE = yes - -# Enable Unicode -UNICODE_ENABLE = yes \ No newline at end of file From 2e99ece8e0c4084b03b4c9b11b8c166942b4bf70 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 12:56:25 -0500 Subject: [PATCH 232/326] update readme details --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c57062e..050cf3f 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # *ew*pratten's *config* files -This repository stores *most* of my common config files. It is designed to be deployable to pretty much any UNIX-like system. Assuming ideal conditions, any machine is one `./install` away from behaving like my personal workstation. +This repository stores most of my common config files. It is designed to be deployable to pretty much any system. Assuming ideal conditions, any machine is one `sh ./install-` away from behaving like my personal workstation. ## Setup The scripts in this repository have the following dependencies: -- Git +- Git (optional, extremely recommended) - ZSH (optional, recommended) - Neovim (optional, recommended) @@ -17,7 +17,7 @@ mkdir -p ~/.config && cd ~/.config git clone https://github.com/ewpratten/ewconfig cd ewconfig -# Linux +# Linux & BSD & probably MacOS (untested) sh ./install-linux.sh # Windows, with GIT BASH From 6f28a078aca292f0bce8c80ae2ae117ecaece04f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 13:10:36 -0500 Subject: [PATCH 233/326] Bring in ferris sweep --- keyboards/qmk/keymaps/ferris/combos.c | 87 +++++++++++++++++++++++++++ keyboards/qmk/keymaps/ferris/config.h | 28 +++++++++ keyboards/qmk/keymaps/ferris/keymap.c | 82 +++++++++++++++++++++++++ keyboards/qmk/keymaps/ferris/rules.mk | 9 +++ scripts/qmk-helper | 7 ++- 5 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 keyboards/qmk/keymaps/ferris/combos.c create mode 100644 keyboards/qmk/keymaps/ferris/config.h create mode 100644 keyboards/qmk/keymaps/ferris/keymap.c create mode 100644 keyboards/qmk/keymaps/ferris/rules.mk diff --git a/keyboards/qmk/keymaps/ferris/combos.c b/keyboards/qmk/keymaps/ferris/combos.c new file mode 100644 index 0000000..79836ec --- /dev/null +++ b/keyboards/qmk/keymaps/ferris/combos.c @@ -0,0 +1,87 @@ +#include QMK_KEYBOARD_H + + +#define MAKE_COMBO_INPUTS(name, inputs...) const uint16_t PROGMEM combo_inputs_##name[] = {inputs, COMBO_END}; + + +// Combo tokens. These are used to identify combos for later processing if needed. +enum combos { + // Combo that uses both pinky fingers to produce an keypress + COMBO_PINKY_ENTER, + // Combo that uses both ring fingers to produce a keypress + // COMBO_RING_BACKSPC, + // Combo that uses the ring fingers to send a semicolon + COMBO_RING_SCLN, + // Copbo that uses the pinky fingers to send escape + COMBO_PINKY_ESC, + + // ASETNIOP + ASETNIOP_AE_Q, + ASETNIOP_RA_W, + ASETNIOP_RE_Z, + ASETNIOP_SA_X, + ASETNIOP_SR_F, + ASETNIOP_TA_P, + ASETNIOP_TR_C, + ASETNIOP_TS_D, + ASETNIOP_TN_B, + ASETNIOP_TE_V, + ASETNIOP_TI_G, + ASETNIOP_NA_J, + ASETNIOP_NR_K, + ASETNIOP_NS_M, + ASETNIOP_NE_H, + ASETNIOP_NO_L, + ASETNIOP_EI_U, + ASETNIOP_IN_Y, +}; + +// Define all the input combinations needed for the combos +MAKE_COMBO_INPUTS(COMBO_PINKY_ENTER, KC_A, KC_O) +MAKE_COMBO_INPUTS(COMBO_RING_SCLN, KC_R, KC_I) +MAKE_COMBO_INPUTS(COMBO_PINKY_ESC, KC_Q, KC_BSPC) +// MAKE_COMBO_INPUTS(COMBO_RING_BACKSPC, KC_R, KC_I) +MAKE_COMBO_INPUTS(ASETNIOP_AE_Q, KC_A, KC_E) +MAKE_COMBO_INPUTS(ASETNIOP_RA_W, KC_R, KC_A) +MAKE_COMBO_INPUTS(ASETNIOP_RE_Z, KC_R, KC_E) +MAKE_COMBO_INPUTS(ASETNIOP_SA_X, KC_S, KC_A) +MAKE_COMBO_INPUTS(ASETNIOP_SR_F, KC_S, KC_R) +MAKE_COMBO_INPUTS(ASETNIOP_TA_P, KC_T, KC_A) +MAKE_COMBO_INPUTS(ASETNIOP_TR_C, KC_T, KC_R) +MAKE_COMBO_INPUTS(ASETNIOP_TS_D, KC_T, KC_S) +MAKE_COMBO_INPUTS(ASETNIOP_TN_B, KC_T, KC_N) +MAKE_COMBO_INPUTS(ASETNIOP_TE_V, KC_T, KC_E) +MAKE_COMBO_INPUTS(ASETNIOP_TI_G, KC_T, KC_I) +MAKE_COMBO_INPUTS(ASETNIOP_NA_J, KC_N, KC_A) +MAKE_COMBO_INPUTS(ASETNIOP_NR_K, KC_N, KC_R) +MAKE_COMBO_INPUTS(ASETNIOP_NS_M, KC_N, KC_S) +MAKE_COMBO_INPUTS(ASETNIOP_NE_H, KC_N, KC_E) +MAKE_COMBO_INPUTS(ASETNIOP_NO_L, KC_N, KC_O) +MAKE_COMBO_INPUTS(ASETNIOP_EI_U, KC_E, KC_I) +MAKE_COMBO_INPUTS(ASETNIOP_IN_Y, KC_I, KC_N) + +// Map everything together +combo_t key_combos[COMBO_COUNT] = { + [COMBO_PINKY_ENTER] = COMBO(combo_inputs_COMBO_PINKY_ENTER, KC_ENT), + [COMBO_RING_SCLN] = COMBO(combo_inputs_COMBO_RING_SCLN, KC_SCLN), + [COMBO_PINKY_ESC] = COMBO(combo_inputs_COMBO_PINKY_ESC, KC_ESC), + // [COMBO_RING_BACKSPC] = COMBO(combo_inputs_COMBO_RING_BACKSPC, KC_BSPC), + [ASETNIOP_AE_Q] = COMBO(combo_inputs_ASETNIOP_AE_Q, KC_Q), + [ASETNIOP_RA_W] = COMBO(combo_inputs_ASETNIOP_RA_W, KC_W), + [ASETNIOP_RE_Z] = COMBO(combo_inputs_ASETNIOP_RE_Z, KC_Z), + [ASETNIOP_SA_X] = COMBO(combo_inputs_ASETNIOP_SA_X, KC_X), + [ASETNIOP_SR_F] = COMBO(combo_inputs_ASETNIOP_SR_F, KC_F), + [ASETNIOP_TA_P] = COMBO(combo_inputs_ASETNIOP_TA_P, KC_P), + [ASETNIOP_TR_C] = COMBO(combo_inputs_ASETNIOP_TR_C, KC_C), + [ASETNIOP_TS_D] = COMBO(combo_inputs_ASETNIOP_TS_D, KC_D), + [ASETNIOP_TN_B] = COMBO(combo_inputs_ASETNIOP_TN_B, KC_B), + [ASETNIOP_TE_V] = COMBO(combo_inputs_ASETNIOP_TE_V, KC_V), + [ASETNIOP_TI_G] = COMBO(combo_inputs_ASETNIOP_TI_G, KC_G), + [ASETNIOP_NA_J] = COMBO(combo_inputs_ASETNIOP_NA_J, KC_J), + [ASETNIOP_NR_K] = COMBO(combo_inputs_ASETNIOP_NR_K, KC_K), + [ASETNIOP_NS_M] = COMBO(combo_inputs_ASETNIOP_NS_M, KC_M), + [ASETNIOP_NE_H] = COMBO(combo_inputs_ASETNIOP_NE_H, KC_H), + [ASETNIOP_NO_L] = COMBO(combo_inputs_ASETNIOP_NO_L, KC_L), + [ASETNIOP_EI_U] = COMBO(combo_inputs_ASETNIOP_EI_U, KC_U), + [ASETNIOP_IN_Y] = COMBO(combo_inputs_ASETNIOP_IN_Y, KC_Y), +}; \ No newline at end of file diff --git a/keyboards/qmk/keymaps/ferris/config.h b/keyboards/qmk/keymaps/ferris/config.h new file mode 100644 index 0000000..389901d --- /dev/null +++ b/keyboards/qmk/keymaps/ferris/config.h @@ -0,0 +1,28 @@ +#pragma once + +// Tapdance settings +#define TAPPING_TERM 50 +#define TAPPING_TERM_PER_KEY +#define RETRO_TAPPING // https://docs.qmk.fm/#/tap_hold?id=retro-tapping + +// Space cadet on control key +#define LCPO_KEYS KC_LCTL, KC_LSFT, KC_0 + +// // Force constant-speed controls for mouse movement +// #define MK_3_SPEED +// #define MK_MOMENTARY_ACCEL + +// // Override the mode-2 speed +// #define MK_C_OFFSET_1 4 // Defaut: 4 + +// Bootloader settings +#define BOOTMAGIC_LITE_ROW 0 +#define BOOTMAGIC_LITE_COLUMN 0 + +// Chording config +#define FORCE_NKRO +// #define COMBO_COUNT 3 +#define COMBO_COUNT 21 + +// Settings for enabling experiments +#define ENABLE_ASETNIOP \ No newline at end of file diff --git a/keyboards/qmk/keymaps/ferris/keymap.c b/keyboards/qmk/keymaps/ferris/keymap.c new file mode 100644 index 0000000..3db33d0 --- /dev/null +++ b/keyboards/qmk/keymaps/ferris/keymap.c @@ -0,0 +1,82 @@ +#include QMK_KEYBOARD_H + +// Combo magic +#include "combos.c" + +// Layer definitions +enum ferris_layers { + _MODMAK, + _NUMERIC, + _UTILITY, + _MACROS, + _RAINBOW, +}; + +// Shorthands +#define LD_TERM LGUI(KC_ENT) +#define CC_QUIT LGUI(LSFT(KC_Q)) +#define CC_COMM LCTL(KC_SLSH) +#define CC_FMT LCTL(LSFT(KC_I)) + +// clang-format off +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + [_MODMAK] = LAYOUT( + KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_BSPC, + KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, + KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_M, KC_K, KC_COMM, KC_DOT, + KC_LSFT, MO(_MACROS), LT(_UTILITY, KC_SPACE), LT(_NUMERIC, KC_SPACE) + ), + + [_NUMERIC] = LAYOUT( + KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, /**/ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, + KC_1, KC_2, KC_3, KC_4, KC_5, /**/ KC_6, KC_7, KC_8, KC_9, KC_0, + KC_LALT, KC_NO, KC_NO, KC_NO, TO(_MODMAK), /**/ KC_LGUI, KC_EQL, KC_MINS, KC_F11, KC_F12, + KC_LSFT, KC_LCTL, /**/ KC_NO, KC_NO + ), + + [_UTILITY] = LAYOUT( + KC_Q, KC_VOLD, KC_VOLU, KC_NO, KC_PSCR, /**/ LD_TERM, KC_HOME, KC_PGUP, KC_PGDN, KC_DEL, + KC_MPRV, KC_MPLY, KC_MNXT, KC_NO, KC_TAB, /**/ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_END, + KC_NO, KC_NO, KC_NO, CC_FMT, CC_COMM, /**/ KC_QUOTE, KC_SLSH, KC_LBRC, KC_RBRC, KC_BSLS, + KC_LSFT, KC_LCTL, /**/ KC_NO, KC_LGUI + ), + + [_MACROS] = LAYOUT( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, TO(_RAINBOW), + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO + ), + + [_RAINBOW] = LAYOUT( + KC_ESC, KC_Q, KC_W, KC_E, KC_5, TO(_MODMAK), KC_NO, KC_NO, KC_NO, KC_NO, + KC_LSFT, KC_A, KC_S, KC_D, KC_G, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_SPACE, KC_X, KC_NO, KC_NO + ) +}; +// clang-format on + +/** THIS IS FOR CREATING A NEW KEYMAP ** + [_UNSET_] = LAYOUT( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO + ) +*/ + +// Overrides for the tapping terms. +uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + // Space cadet needs to be much slower than my default + case SC_LSPO: + case SC_LCPO: + return 200; + case LT(_NUMERIC, KC_SPACE): + return 1000; + default: + return TAPPING_TERM; + } +} diff --git a/keyboards/qmk/keymaps/ferris/rules.mk b/keyboards/qmk/keymaps/ferris/rules.mk new file mode 100644 index 0000000..d02eca0 --- /dev/null +++ b/keyboards/qmk/keymaps/ferris/rules.mk @@ -0,0 +1,9 @@ +# Override the default bootloader since I am using a non-standard MCU +BOOTLOADER = qmk-dfu + +# Enable bootloader keys +BOOTMAGIC_ENABLE = yes + +# Set up chording support +FORCE_NKRO = yes +COMBO_ENABLE = yes \ No newline at end of file diff --git a/scripts/qmk-helper b/scripts/qmk-helper index cc4301d..2305283 100755 --- a/scripts/qmk-helper +++ b/scripts/qmk-helper @@ -119,7 +119,7 @@ def main() -> int: ap.add_argument( "keyboard", help="Keyboard to build/flash", - choices=["tg4x"], + choices=["tg4x", "ferris/sweep"], ) ap.add_argument("--flash-mode", "-f", help="Flash mode to use", default="flash") ap.add_argument( @@ -140,9 +140,12 @@ def main() -> int: # Refresh the QMK repository refresh_qmk_repo() + + # Figure out the keymap name + keymap = args.keyboard.split("/")[0] # Copy the keymap - copy_keymap(args.keyboard) + copy_keymap(keymap) # Handle the modes if args.mode == "build": From 580ba6a62b3d93364b758d0eecb24b117363632e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 13:11:42 -0500 Subject: [PATCH 234/326] Add a pre-check --- scripts/qmk-helper | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/qmk-helper b/scripts/qmk-helper index 2305283..ec3821d 100755 --- a/scripts/qmk-helper +++ b/scripts/qmk-helper @@ -140,7 +140,7 @@ def main() -> int: # Refresh the QMK repository refresh_qmk_repo() - + # Figure out the keymap name keymap = args.keyboard.split("/")[0] @@ -151,6 +151,14 @@ def main() -> int: if args.mode == "build": build_keymap(args.keyboard) elif args.mode == "flash": + # Make sure that the flash mode is valid + if args.keyboard == "ferris-sweep" and args.flash_mode not in ["dfu-split-left", "dfu-split-right"]: + logger.error( + "Invalid flash mode. Must be one of: dfu-split-left, dfu-split-right" + ) + return 1 + + # Flash flash_keymap(args.keyboard, args.flash_mode) return 0 From 07340037785808afa82d381d415d7cc9fb1fc504 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 13:34:47 -0500 Subject: [PATCH 235/326] speed up aspath script --- scripts/aspath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/aspath b/scripts/aspath index 59d3467..54d2803 100755 --- a/scripts/aspath +++ b/scripts/aspath @@ -8,7 +8,7 @@ if [ -z "$1" ]; then fi # Parse out the ASNs -asns=$( mtr -jzc1 $1 | jq ".report.hubs[].ASN" | tr -d "\"" | uniq ) +asns=$( mtr -jzc1 -Z1 -G0.25 $1 | jq ".report.hubs[].ASN" | tr -d "\"" | uniq ) # For each line for asn in $asns; do From 0a6d46c76ab295165f394359e4c8d4a9803eac76 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 16:31:03 -0500 Subject: [PATCH 236/326] pure magic --- scripts/ableton-linux | 135 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 scripts/ableton-linux diff --git a/scripts/ableton-linux b/scripts/ableton-linux new file mode 100755 index 0000000..32780f1 --- /dev/null +++ b/scripts/ableton-linux @@ -0,0 +1,135 @@ +#! /usr/bin/env python3 +import argparse +import os +import sys +import logging +import subprocess +import shutil +import time +from pathlib import Path + +logger = logging.getLogger(__name__) + +WINEASIO_SRC_PATH = Path("~/src/wineasio").expanduser() + + +def build_wineasio(): + # If the wineasio source directory doesn't exist, clone it + if not WINEASIO_SRC_PATH.is_dir(): + logger.info("Cloning wineasio source") + subprocess.check_call( + [ + "git", + "clone", + "https://github.com/wineasio/wineasio", + str(WINEASIO_SRC_PATH), + ] + ) + subprocess.check_call( + ["git", "submodule", "update", "--init", "--recursive"], + cwd=str(WINEASIO_SRC_PATH), + ) + + # Make sure `pipewire-jack` is installed + logger.info("Installing pipewire-jack") + + # Call make to build 64-bit libs + logger.info("Building wineasio") + try: + subprocess.check_call(["make", "64"], cwd=str(WINEASIO_SRC_PATH)) + except subprocess.CalledProcessError: + logger.error("Failed to build wineasio") + logger.info( + "Make sure you have `pipewire-jack-audio-connection-kit-devel` installed" + ) + logger.info("Make sure you have `wine-devel` installed") + sys.exit(1) + + # We need to copy the libs for wine to find them + logger.info("Copying wineasio libs") + subprocess.check_call( + ["sudo", "cp", "build64/wineasio64.dll", "/usr/lib64/wine/x86_64-windows/"], + cwd=str(WINEASIO_SRC_PATH), + ) + subprocess.check_call( + ["sudo", "cp", "build64/wineasio64.dll.so", "/usr/lib64/wine/x86_64-unix/"], + cwd=str(WINEASIO_SRC_PATH), + ) + + +def bottles_winepfx_from_name(bottle_name: str) -> Path: + return Path("~/.local/share/bottles/bottles/").expanduser() / ( + bottle_name.replace(" ", "-") + ) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="ableton-linux", description="Executes Ableton on Linux" + ) + ap.add_argument( + "--bottle", "-b", help="Use the specified bottle", default="Ableton 11 Standard" + ) + ap.add_argument( + "--program", "-p", help="Program to run", default="Ableton Live 11 Standard" + ) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Ensure we have wineasio + if not (WINEASIO_SRC_PATH / "build64").exists(): + build_wineasio() + + # Figure out the wineprefix + wineprefix = bottles_winepfx_from_name(args.bottle) + logger.info(f"Wine prefix is: {wineprefix}") + + # Ensure that the bottle has the wineasio dll + if not (wineprefix / ".wineasio-installed").is_file(): + logger.info("Registering wineasio") + subprocess.check_call( + [WINEASIO_SRC_PATH / "wineasio-register"], + env={"WINEPREFIX": str(wineprefix)}, + ) + shutil.copy( + WINEASIO_SRC_PATH / "build64" / "wineasio64.dll.so", + wineprefix / "drive_c" / "windows" / "system" / "wineasio64.dll", + ) + shutil.copy( + WINEASIO_SRC_PATH / "build64" / "wineasio64.dll.so", + wineprefix / "drive_c" / "windows" / "system32" / "wineasio64.dll", + ) + (wineprefix / ".wineasio-installed").touch() + + logger.info("Waiting 15 seconds to let wine do its thing") + time.sleep(15) + + # Build a modified environment for ableton + ableton_env = os.environ.copy() + ableton_env.update( + { + "WINEASIO_NUMBER_INPUTS": "16", + "WINEASIO_NUMBER_OUTPUTS": "16", + "WINEASIO_CONNECT_TO_HARDWARE": "1", + } + ) + + # Launch Ableton via bottles + logger.info("Launching Ableton") + return_code = subprocess.call( + ["bottles-cli", "run", "-b", args.bottle, "-p", args.program], env=ableton_env + ) + return return_code + + +if __name__ == "__main__": + sys.exit(main()) From dacd853295c15cc2acfa31738743e6d4bc195b36 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 9 Nov 2023 16:34:00 -0500 Subject: [PATCH 237/326] Add an error --- scripts/ableton-linux | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/ableton-linux b/scripts/ableton-linux index 32780f1..a0d02a5 100755 --- a/scripts/ableton-linux +++ b/scripts/ableton-linux @@ -84,6 +84,11 @@ def main() -> int: level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s", ) + + # Ensure we have bottles + if not shutil.which("bottles-cli"): + logger.error("You can't do this without bottles installed") + return 1 # Ensure we have wineasio if not (WINEASIO_SRC_PATH / "build64").exists(): From 68af550e4c27906e4977d8e566fb2ad490cd5d4f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 12 Nov 2023 16:04:56 -0500 Subject: [PATCH 238/326] Add support for kde connect --- scripts/ufw-gen | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ufw-gen b/scripts/ufw-gen index 700bd08..5a120c7 100755 --- a/scripts/ufw-gen +++ b/scripts/ufw-gen @@ -19,6 +19,10 @@ PROFILES = { "comment": "Zola", "ports": [(1111, "tcp")], }, + "kdeconnect":{ + "comment":"KDE Connect", + "ports":[("1714:1764", "udp"), ("1714:1764", "tcp")] + } } From 8cd3ecee172e1a0011f79e97b88f377a84b47a16 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 13 Nov 2023 09:33:53 -0500 Subject: [PATCH 239/326] Add a macro for going to dev area --- configs/shells/bash/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index dc932a4..5457c72 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -63,6 +63,7 @@ fi # If we are running in a studio environment if [ ! -z "$EWP_IN_GURU_ENVIRONMENT" ]; then alias guru_launcher3="python $GURU_PYTHON_ROOT/env/guru_launcher3.py" + alias cd-dev="cd /s/development/epratten" fi # Kill via pgrep From 39bf9834b4b4eb304b6bc7de692aa6c4e57a9c1f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 13 Nov 2023 10:13:04 -0500 Subject: [PATCH 240/326] Build a tool that can display tracebacks nicely --- scripts/pytb | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100755 scripts/pytb diff --git a/scripts/pytb b/scripts/pytb new file mode 100755 index 0000000..758d440 --- /dev/null +++ b/scripts/pytb @@ -0,0 +1,119 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import re +from pathlib import Path +from rich.console import Console +from rich.syntax import Syntax +from datetime import datetime + +logger = logging.getLogger(__name__) + +LINE_NUMBER_RE = re.compile(r", line \d+,") +OUTPUT_ROOT = Path("~/Pictures/pytb").expanduser() + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="pytb", description="Tool for analyzing Python back traces" + ) + ap.add_argument("--file", "-f", help="Read from file instead of stdin", type=Path) + ap.add_argument( + "--no-strip-referer", help="Strip referer from flask tbs", action="store_true" + ) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Attempt to read from file + if args.file: + tb_lines = args.file.read_text().splitlines() + else: + # Check if the shell is interactive + if sys.stdin.isatty(): + print("Please paste the backtrace and press Ctrl+D:") + + # Read from stdin until EOF + try: + tb_lines = "".join(list(sys.stdin)).splitlines() + except KeyboardInterrupt: + print("\nKeyboard interrupt detected, exiting...") + return 1 + + # Seek to the first line of the backtrace + for start_idx, line in enumerate(tb_lines): + if line.startswith("Traceback"): + break + else: + logger.error("No traceback found") + return 1 + + # Group the traceback lines into frames + frames = [] + is_in_frame = False + for line in tb_lines[start_idx:]: + if line.startswith("File "): + is_in_frame = True + frames.append([line]) + elif is_in_frame: + frames[-1].append(line) + + # Handle the frames + output_lines = [] + for frame in frames: + # Figure out the file + file = Path(frame[0].split('"')[1]) + line_num = int(LINE_NUMBER_RE.search(frame[0]).group(0)[6:-1]) + + # Print the actual code + for idx, statement in enumerate(frame[1:]): + # Remove left padding + statement = statement.lstrip() + + # Remove referer if needed + if not args.no_strip_referer: + statement = statement.split(", referer")[0] + + # Build a context string if needed + context = f" # {file}#{line_num}" if idx == 0 else "" + + # Print the line + output_lines.append((statement, context)) + + # Figure out the longest statement + longest_statement = max(len(line[0]) for line in output_lines) + + # Build the lines, padding the statements so that the files line up + output = "" + for statement, context in output_lines: + output += f"{statement.ljust(longest_statement)}{context}\n" + + # remove any trailing newlines + output = output.rstrip() + + # Pass over to rich to do the syntax highlighting + console = Console(record=True) + console.print(Syntax(output, "python", background_color="default")) + + # Export an image + file_name = f"Traceback {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" + if args.file: + file_name += f" ({args.file.stem})" + file_name += ".svg" + OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) + console.save_svg(OUTPUT_ROOT / file_name, title="Python Traceback Visualizer (a tool by ewpratten)") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From f2ce365c4bba0d8e76c459ed99f4e132c7dd45a2 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 13 Nov 2023 10:19:14 -0500 Subject: [PATCH 241/326] Adjust console width for better output visualization. --- scripts/pytb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/pytb b/scripts/pytb index 758d440..6ec21b4 100755 --- a/scripts/pytb +++ b/scripts/pytb @@ -96,12 +96,13 @@ def main() -> int: output = "" for statement, context in output_lines: output += f"{statement.ljust(longest_statement)}{context}\n" + longest_line = max(len(line) for line in output.splitlines()) # remove any trailing newlines output = output.rstrip() # Pass over to rich to do the syntax highlighting - console = Console(record=True) + console = Console(record=True, width=longest_line+1) console.print(Syntax(output, "python", background_color="default")) # Export an image @@ -110,7 +111,7 @@ def main() -> int: file_name += f" ({args.file.stem})" file_name += ".svg" OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) - console.save_svg(OUTPUT_ROOT / file_name, title="Python Traceback Visualizer (a tool by ewpratten)") + console.save_svg(OUTPUT_ROOT / file_name, title="Evan's Python Traceback Visualizer") return 0 From c7cf7b0c27d13607b10fc98e144184c392ee469e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 14 Nov 2023 10:42:17 -0500 Subject: [PATCH 242/326] Various bugfixes --- scripts/guru-shell | 3 +++ scripts/pytb | 30 ++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/scripts/guru-shell b/scripts/guru-shell index ec4bd21..ede9ec5 100755 --- a/scripts/guru-shell +++ b/scripts/guru-shell @@ -39,6 +39,9 @@ export GURU_PYTHON_ROOT="$s_drive/$studio2023_path" export PYTHONPATH="$GURU_PYTHON_ROOT/env$pathsep$PYTHONPATH" export PYTHONPATH="$GURU_PYTHON_ROOT$pathsep$PYTHONPATH" +# Remove anything from PYTHONPATH that contains Maya_Shared. +export PYTHONPATH=$(echo $PYTHONPATH | sed "s/[^$pathsep]*Maya_Shared[^$pathsep]*//g" | sed "s/$pathsep$pathsep/$pathsep/g" | sed "s/^$pathsep//g" | sed "s/$pathsep$//g") + # Update the PATH to point to the studio's install of python if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH" diff --git a/scripts/pytb b/scripts/pytb index 6ec21b4..fe0bddb 100755 --- a/scripts/pytb +++ b/scripts/pytb @@ -23,6 +23,7 @@ def main() -> int: ap.add_argument( "--no-strip-referer", help="Strip referer from flask tbs", action="store_true" ) + ap.add_argument("--trace-only", help="Only print the trace", action="store_true") ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) @@ -61,7 +62,7 @@ def main() -> int: frames = [] is_in_frame = False for line in tb_lines[start_idx:]: - if line.startswith("File "): + if line.lstrip().startswith("File "): is_in_frame = True frames.append([line]) elif is_in_frame: @@ -90,28 +91,41 @@ def main() -> int: output_lines.append((statement, context)) # Figure out the longest statement - longest_statement = max(len(line[0]) for line in output_lines) + longest_statement = max(len(line[0]) for line in output_lines[:-1]) # Build the lines, padding the statements so that the files line up output = "" for statement, context in output_lines: output += f"{statement.ljust(longest_statement)}{context}\n" - longest_line = max(len(line) for line in output.splitlines()) - + # remove any trailing newlines output = output.rstrip() + # Figure out the longest line + output_trace = "\n".join(output.splitlines()[:-1]) + output_error = output.splitlines()[-1] + if args.trace_only: + longest_line = max(len(line) for line in output_trace.splitlines()) + else: + longest_line = max(len(line) for line in output.splitlines()) + # Pass over to rich to do the syntax highlighting - console = Console(record=True, width=longest_line+1) - console.print(Syntax(output, "python", background_color="default")) - + console = Console(record=True, width=longest_line + 1) + console.print(Syntax(output_trace, "python", background_color="default")) + if not args.trace_only: + console.print( + Syntax(output_error, "python", background_color="default") + ) + # Export an image file_name = f"Traceback {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" if args.file: file_name += f" ({args.file.stem})" file_name += ".svg" OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) - console.save_svg(OUTPUT_ROOT / file_name, title="Evan's Python Traceback Visualizer") + console.save_svg( + OUTPUT_ROOT / file_name, title="Evan's Python Traceback Visualizer" + ) return 0 From 27d0e900368764c1a2a148909110219ef6ed2337 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 15 Nov 2023 10:03:37 -0500 Subject: [PATCH 243/326] Support Ableton Suite --- scripts/ableton-linux | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/ableton-linux b/scripts/ableton-linux index a0d02a5..f9e6c95 100755 --- a/scripts/ableton-linux +++ b/scripts/ableton-linux @@ -69,10 +69,10 @@ def main() -> int: prog="ableton-linux", description="Executes Ableton on Linux" ) ap.add_argument( - "--bottle", "-b", help="Use the specified bottle", default="Ableton 11 Standard" + "--bottle", "-b", help="Use the specified bottle", default="Ableton 11 Suite" ) ap.add_argument( - "--program", "-p", help="Program to run", default="Ableton Live 11 Standard" + "--program", "-p", help="Program to run", default="Ableton Live 11 Suite" ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" @@ -84,7 +84,7 @@ def main() -> int: level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s", ) - + # Ensure we have bottles if not shutil.which("bottles-cli"): logger.error("You can't do this without bottles installed") @@ -114,7 +114,7 @@ def main() -> int: wineprefix / "drive_c" / "windows" / "system32" / "wineasio64.dll", ) (wineprefix / ".wineasio-installed").touch() - + logger.info("Waiting 15 seconds to let wine do its thing") time.sleep(15) @@ -125,6 +125,9 @@ def main() -> int: "WINEASIO_NUMBER_INPUTS": "16", "WINEASIO_NUMBER_OUTPUTS": "16", "WINEASIO_CONNECT_TO_HARDWARE": "1", + "WINEASIO_PREFERRED_BUFFERSIZE": "2048", + "WINEASIO_FIXED_BUFFERSIZE": "1", + # "PIPEWIRE_LATENCY": "2048/48000", # Buffer size / sample rate } ) From 03987e23cb14c22b10ba4f349f5ed853ffe59bba Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 15 Nov 2023 10:03:52 -0500 Subject: [PATCH 244/326] Add PYTHONPATH to load custom python modules and update ssh config for oci-arm --- configs/shells/zsh/.zshrc | 3 +++ configs/ssh/config | 2 +- scripts/sh2img | 47 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100755 scripts/sh2img diff --git a/configs/shells/zsh/.zshrc b/configs/shells/zsh/.zshrc index 26de500..0df886b 100644 --- a/configs/shells/zsh/.zshrc +++ b/configs/shells/zsh/.zshrc @@ -21,6 +21,9 @@ export PATH="$HOME/bin:$PATH" export PATH="$EWCONFIG_ROOT/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" +# I want to be able to load my custom python modules +export PYTHONPATH="$EWCONFIG_ROOT/python_modules:$PYTHONPATH" + # Configure a sane default editor if type -p nvim > /dev/null; then export EDITOR="nvim" diff --git a/configs/ssh/config b/configs/ssh/config index ab276b1..4758a3c 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -84,5 +84,5 @@ Host td-prod td-prod2 td-prod3 td-prod4 # Personal Infra Host oci-arm - HostName oci-arm.ip.ewp.fyi + HostName oci-arm.vpn.ewp.fyi User ubuntu diff --git a/scripts/sh2img b/scripts/sh2img new file mode 100755 index 0000000..126306a --- /dev/null +++ b/scripts/sh2img @@ -0,0 +1,47 @@ +#! /usr/bin/env python +import sys +import os +import subprocess +import argparse +from pathlib import Path +from rich.console import Console +from rich.syntax import Syntax +from datetime import datetime + +def main() -> int: + # Read the arguments + ap = argparse.ArgumentParser(prog="sh2img", description="Generate images from shell commands") + ap.add_argument("command", help="The command to execute", nargs="+") + ap.add_argument("--shell", "-s", help="The shell to use") + args = ap.parse_args() + + # Figure out if we are root + is_root = os.geteuid() == 0 + shell_char = "#" if is_root else "$" + + # Set up the console + console = Console(record=True) + + # Print out the arguments as a command being executed + console.print(f"{shell_char} {' '.join(args.command)}", style="white", highlight=False) + if args.shell: + args.command = [args.shell, "-c", " ".join(args.command)] + + # Execute the program, capturing all output together in one string + output = subprocess.run(args.command, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) + output = output.stdout.decode("utf-8").strip() + + console.width = min(max(len(line) for line in output.splitlines()), 150) + + # Print the output + console.print(output, highlight=False) + + # Save to a file + out_file = Path("~/Pictures/sh2img").expanduser() / f"{datetime.now().timestamp()}.svg" + out_file.parent.mkdir(parents=True, exist_ok=True) + console.save_svg(out_file, title=args.command[0]) + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file From bbdc56f0498f6ec140a022fb63cf29946ca6fe06 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 16 Nov 2023 15:23:23 -0500 Subject: [PATCH 245/326] macros --- configs/shells/bash/.bashrc | 5 ----- configs/shells/bash/macros.sh | 17 +++++++++++++++++ configs/shells/zsh/.zshrc | 4 ++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index 44a9343..abe2c23 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -14,8 +14,3 @@ export PATH="$HOME/.local/bin:$PATH" # A basic prompt to display user@host dir sign export PS1="(${PS1_CTX:-bash}) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" - -# If found, load studio python -# if [ -d "/c/Programs/software/win/core/python/python_3.7.7" ]; then export PATH="/c/Programs/software/win/core/python/python_3.7.7:$PATH"; fi - - diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 5457c72..2a575d3 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -22,6 +22,8 @@ alias flush-dns-cache="sudo systemd-resolve --flush-caches" alias which-ls="ls -la $(which ls)" alias rdns="dig +short -x" alias ufw-status="sudo ufw status numbered" +alias genuuid="python -c 'import uuid; print(uuid.uuid4())'" +alias clipboard="xclip -selection clipboard" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" @@ -220,3 +222,18 @@ ewconfig-run() { $@ cd $cwd } + +# Define a function to emulate gh +gh-emulated() { + if [ $# != 3 ]; then + echo "You don't have gh installed. Emulating its functionality." + echo "Usage: gh repo clone /" + else + git clone https://github.com/$3 + fi +} + +# Only if `gh` is not installed +if ! command -v gh &> /dev/null; then + alias gh=gh-emulated +fi \ No newline at end of file diff --git a/configs/shells/zsh/.zshrc b/configs/shells/zsh/.zshrc index 0df886b..bd683b8 100644 --- a/configs/shells/zsh/.zshrc +++ b/configs/shells/zsh/.zshrc @@ -21,6 +21,10 @@ export PATH="$HOME/bin:$PATH" export PATH="$EWCONFIG_ROOT/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" +# Make sure libs can be found +export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" +export LD_LIBRARY_PATH="/usr/local/lib64:$LD_LIBRARY_PATH" + # I want to be able to load my custom python modules export PYTHONPATH="$EWCONFIG_ROOT/python_modules:$PYTHONPATH" From 2bb7060a79f24999c598b370315649794fd42c4a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 17 Nov 2023 09:31:27 -0500 Subject: [PATCH 246/326] Let core configs work in vim --- configs/nvim/init.vim | 84 +++---------------------------------------- configs/vim/.vimrc | 74 ++++++++++++++++++++++++++++++++++++++ install-linux.sh | 1 + 3 files changed, 79 insertions(+), 80 deletions(-) create mode 100644 configs/vim/.vimrc diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index bdf8063..60e7b49 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -1,12 +1,4 @@ - -" Syntax highlighting -syntax on - -" Enable modeline -set modeline - -" Enable mouse usage -set mouse=a +source ~/.vimrc " Configure the right-click menu if !exists('g:vscode') @@ -21,78 +13,10 @@ if !exists('g:vscode') inoremenu PopUp.Select\ All VG endif -" Tab size -set tabstop=4 -set shiftwidth=4 -set expandtab - -" VSCode-style selection indenting -nnoremap >>_ -nnoremap <<_ -inoremap -vnoremap >gv -vnoremap -inoremap lcw -nnoremap cwl - -" VSCode-style comment toggling -nnoremap :Commentary -vnoremap :Commentary -inoremap :Commentary - -" Force VIM to use system clipboard -set clipboard=unnamedplus - -" Enable per-project vimrc files -set exrc -set secure - -" Enable filetype plugins -set nocompatible -filetype plugin on -syntax on - " Custom syntax highlighting -if !exists('g:vscode') - au BufRead,BufNewFile *.usd set filetype=usda - au BufRead,BufNewFile *.usda set filetype=usda - autocmd FileType usda source ~/.config/nvim/third_party/usda-syntax/vim/usda.vim -endif - -" Hide the intro message -set shortmess+=I - -" Force help documents into new tabs -cnoreabbrev help getcmdtype() == ":" && getcmdline() == 'help' ? 'tab help' : 'help' -cnoreabbrev h getcmdtype() == ":" && getcmdline() == 'h' ? 'tab help' : 'h' - -" Enable spell checking -if !exists('g:vscode') - set spell - set spelllang=en_ca,en_us - set spelloptions=camel - hi clear SpellCap - hi clear SpellRare - - " Disable spellcheck for some file formats - autocmd FileType man setlocal nospell - autocmd FileType diff setlocal nospell - autocmd FileType usda setlocal nospell -endif - -" Configure Diff rendering -hi DiffText ctermfg=White ctermbg=none -hi DiffFile ctermfg=White ctermbg=none cterm=bold -hi DiffIndexLine ctermfg=White ctermbg=none cterm=bold -hi DiffAdd ctermfg=DarkGreen ctermbg=none -hi DiffChange ctermfg=DarkRed ctermbg=none -hi DiffDelete ctermfg=DarkRed ctermbg=none +au BufRead,BufNewFile *.usd set filetype=usda +au BufRead,BufNewFile *.usda set filetype=usda +autocmd FileType usda source ~/.config/nvim/third_party/usda-syntax/vim/usda.vim " Disable the gitgutter background let g:gitgutter_override_sign_column_highlight = 1 diff --git a/configs/vim/.vimrc b/configs/vim/.vimrc new file mode 100644 index 0000000..8e14521 --- /dev/null +++ b/configs/vim/.vimrc @@ -0,0 +1,74 @@ +" Syntax highlighting +syntax on + +" Enable modeline +set modeline + +" Enable mouse usage +set mouse=a + +" Tab size +set tabstop=4 +set shiftwidth=4 +set expandtab + +" VSCode-style selection indenting +nnoremap >>_ +nnoremap <<_ +inoremap +vnoremap >gv +vnoremap +inoremap lcw +nnoremap cwl + +" VSCode-style comment toggling +nnoremap :Commentary +vnoremap :Commentary +inoremap :Commentary + +" Force VIM to use system clipboard +set clipboard=unnamedplus + +" Enable per-project vimrc files +set exrc +set secure + +" Enable filetype plugins +set nocompatible +filetype plugin on +syntax on + +" Hide the intro message +set shortmess+=I + +" Force help documents into new tabs +cnoreabbrev help getcmdtype() == ":" && getcmdline() == 'help' ? 'tab help' : 'help' +cnoreabbrev h getcmdtype() == ":" && getcmdline() == 'h' ? 'tab help' : 'h' + +" Enable spell checking +if !exists('g:vscode') + set spell + set spelllang=en_ca,en_us + set spelloptions=camel + hi clear SpellCap + hi clear SpellRare + + " Disable spellcheck for some file formats + autocmd FileType man setlocal nospell + autocmd FileType diff setlocal nospell + autocmd FileType usda setlocal nospell +endif + +" Configure Diff rendering +hi DiffText ctermfg=White ctermbg=none +hi DiffFile ctermfg=White ctermbg=none cterm=bold +hi DiffIndexLine ctermfg=White ctermbg=none cterm=bold +hi DiffAdd ctermfg=DarkGreen ctermbg=none +hi DiffChange ctermfg=DarkRed ctermbg=none +hi DiffDelete ctermfg=DarkRed ctermbg=none \ No newline at end of file diff --git a/install-linux.sh b/install-linux.sh index 8293c72..934bd47 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -78,6 +78,7 @@ chmod 644 "$HOME/.ssh/config" if type -p chown > /dev/null; then chown "$USER:$USER" "$HOME/.ssh/config"; fi # Configure (neo)Vim +ln -sf $EWCONFIG_ROOT/configs/vim/.vimrc ~/.vimrc ln -sf $EWCONFIG_ROOT/configs/nvim/init.vim ~/.config/nvim/init.vim ln -snf $EWCONFIG_ROOT/configs/nvim/pack ~/.config/nvim/pack ln -snf $EWCONFIG_ROOT/configs/nvim/third_party ~/.config/nvim/third_party From 61ce060bf4c18c64b1af60ce0626000ab33cf0f3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 17 Nov 2023 10:57:59 -0500 Subject: [PATCH 247/326] Show ableton in Discord --- scripts/ableton-linux | 58 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/scripts/ableton-linux b/scripts/ableton-linux index f9e6c95..35cb45a 100755 --- a/scripts/ableton-linux +++ b/scripts/ableton-linux @@ -6,11 +6,14 @@ import logging import subprocess import shutil import time +import pypresence from pathlib import Path logger = logging.getLogger(__name__) WINEASIO_SRC_PATH = Path("~/src/wineasio").expanduser() +DISCORD_CLIENT_ID = 1175091631913963610 +DISCORD_ICON = "ableton_grey" def build_wineasio(): @@ -68,12 +71,18 @@ def main() -> int: ap = argparse.ArgumentParser( prog="ableton-linux", description="Executes Ableton on Linux" ) + ap.add_argument( + "--no-presence", "-n", help="Hide activity from Discord", action="store_true" + ) ap.add_argument( "--bottle", "-b", help="Use the specified bottle", default="Ableton 11 Suite" ) ap.add_argument( "--program", "-p", help="Program to run", default="Ableton Live 11 Suite" ) + ap.add_argument( + "--dry-run", help="Don't actually launch Ableton", action="store_true" + ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) @@ -90,8 +99,18 @@ def main() -> int: logger.error("You can't do this without bottles installed") return 1 + # Configure discord presence + discord_presence = pypresence.Presence(DISCORD_CLIENT_ID) + discord_presence.connect() + launch_start = int(time.time()) + # Ensure we have wineasio if not (WINEASIO_SRC_PATH / "build64").exists(): + discord_presence.update( + start=launch_start, + large_image=DISCORD_ICON, + details="Compiling WineASIO...", + ) build_wineasio() # Figure out the wineprefix @@ -101,6 +120,11 @@ def main() -> int: # Ensure that the bottle has the wineasio dll if not (wineprefix / ".wineasio-installed").is_file(): logger.info("Registering wineasio") + discord_presence.update( + start=launch_start, + large_image=DISCORD_ICON, + details="Registering WineASIO with Ableton...", + ) subprocess.check_call( [WINEASIO_SRC_PATH / "wineasio-register"], env={"WINEPREFIX": str(wineprefix)}, @@ -131,12 +155,36 @@ def main() -> int: } ) - # Launch Ableton via bottles - logger.info("Launching Ableton") - return_code = subprocess.call( - ["bottles-cli", "run", "-b", args.bottle, "-p", args.program], env=ableton_env + # Update the presence message + discord_presence.update( + start=launch_start, + large_image=DISCORD_ICON, + details="Working on a project", + buttons=[ + {"label": "Check out my music!", "url": "https://ewpratten.com/music"} + ], ) - return return_code + + # Immediately cancel the presence if requested + if args.no_presence: + discord_presence.close() + + # Launch Ableton via bottles + if not args.dry_run: + logger.info("Launching Ableton") + return_code = subprocess.call( + ["bottles-cli", "run", "-b", args.bottle, "-p", args.program], + env=ableton_env, + ) + discord_presence.close() + return return_code + + else: + logger.info("Dry run, not launching Ableton") + logger.info("Press enter to continue") + input() + discord_presence.close() + return 0 if __name__ == "__main__": From 9867d0c92cd8522c7d8083e1e71f34206e068071 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 17 Nov 2023 10:58:12 -0500 Subject: [PATCH 248/326] Add a fix for bad TOTP codes --- scripts/guru-vpn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/guru-vpn b/scripts/guru-vpn index b974c6b..fa5c189 100755 --- a/scripts/guru-vpn +++ b/scripts/guru-vpn @@ -71,6 +71,9 @@ def handle_connect(args: argparse.Namespace) -> int: # Fetch the credentials from the Yubikey oath_code = get_oath_code("Guru") print(f"Using OATH code: {oath_code}") + if not len(str(oath_code)) == 6: + print("Invalid OATH code length. Try again in a minute.", file=sys.stderr) + return 1 # Construct the one-time password password = f"{base_password}{oath_code}" From fa2248c98af716a983d594072db82c0249af23fa Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 17 Nov 2023 19:56:34 -0500 Subject: [PATCH 249/326] Implement customized python REPL --- configs/gnome/desktop-settings.sh | 2 +- configs/python/python_startup.py | 95 +++++++++++++++++++++++++++++++ configs/shells/bash/.bashrc | 4 ++ configs/shells/zsh/.zshrc | 1 + install-linux.sh | 4 +- scripts/tinker | 11 ++++ 6 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 configs/python/python_startup.py create mode 100755 scripts/tinker diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index c0867be..634ab70 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -55,7 +55,7 @@ if [ "$keybindings" = "[]" ] || [ "$keybindings" = "@as []" ]; then # Allow Mod+Shift+Enter to open python gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/ name "Python REPL" - gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/ command "gnome-terminal -- python3" + gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/ command "gnome-terminal -- $EWCONFIG_ROOT/.config/ewconfig/scripts/tinker" gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/ binding "Return" fi diff --git a/configs/python/python_startup.py b/configs/python/python_startup.py new file mode 100644 index 0000000..0c4a03c --- /dev/null +++ b/configs/python/python_startup.py @@ -0,0 +1,95 @@ +"""Python Startup file. Used to customize the Python REPL""" +import sys +import os + +# Global stuff +IS_IN_TINKER_MODE = bool(os.environ.get("PYTHON_TINKER_MODE")) +COLOR_ALLOWED = not bool(os.environ.get("NO_COLOR")) + + +def colored_string(text: str, color: str) -> str: + if COLOR_ALLOWED: + return "\033[" + color + "m" + text + "\033[0m" + else: + return text + + +# Configure the prompt +class Prompt: + def __init__(self): + self.prompt = colored_string(">>> ", "36") + + def __str__(self): + return self.prompt + + +class MultiLinePrompt: + def __str__(self): + return colored_string("... ", "33") + # return " " + + +# Hook up the prompts +sys.ps1 = Prompt() +sys.ps2 = MultiLinePrompt() + +# "Tinker mode" - automatically import common things +if IS_IN_TINKER_MODE: + print( + colored_string( + "Running in tinker mode. Additional modules are available.", "33" + ) + ) + + # Basics + import time + import json + from pathlib import Path + from dataclasses import dataclass + from typing import ( + List, + Dict, + Tuple, + Set, + Optional, + Union, + Any, + Callable, + Iterable, + Generator, + ) + from pprint import pprint + from datetime import datetime + from textwrap import dedent + from base64 import b64encode, b64decode + + # Math stuff + try: + import numpy as np + + np.set_printoptions(suppress=True) + _vec = lambda *fields: np.array([*fields]) + pi = np.pi + except ImportError: + pass + try: + from pyquaternion import Quaternion + except ImportError: + pass + try: + import matplotlib.pyplot as plt + except ImportError: + pass + + +# If we aren't in tinker mode, un-import sys and os +if not IS_IN_TINKER_MODE: + del sys + del os + +# Clean up other stuff +del IS_IN_TINKER_MODE +del COLOR_ALLOWED +del colored_string +del Prompt +del MultiLinePrompt \ No newline at end of file diff --git a/configs/shells/bash/.bashrc b/configs/shells/bash/.bashrc index abe2c23..b7782d2 100644 --- a/configs/shells/bash/.bashrc +++ b/configs/shells/bash/.bashrc @@ -12,5 +12,9 @@ export PATH="$HOME/bin:$PATH" export PATH="$EWCONFIG_ROOT/scripts:$PATH" export PATH="$HOME/.local/bin:$PATH" +# I want to be able to load my custom python modules +export PYTHONPATH="$EWCONFIG_ROOT/python_modules:$PYTHONPATH" +export PYTHONSTARTUP="$EWCONFIG_ROOT/configs/python/python_startup.py" + # A basic prompt to display user@host dir sign export PS1="(${PS1_CTX:-bash}) \[\e[0;32m\]\u@\h \[\e[0;36m\]\w \[\e[0;36m\]\$ \[\e[0m\]" diff --git a/configs/shells/zsh/.zshrc b/configs/shells/zsh/.zshrc index bd683b8..c81007e 100644 --- a/configs/shells/zsh/.zshrc +++ b/configs/shells/zsh/.zshrc @@ -27,6 +27,7 @@ export LD_LIBRARY_PATH="/usr/local/lib64:$LD_LIBRARY_PATH" # I want to be able to load my custom python modules export PYTHONPATH="$EWCONFIG_ROOT/python_modules:$PYTHONPATH" +export PYTHONSTARTUP="$EWCONFIG_ROOT/configs/python/python_startup.py" # Configure a sane default editor if type -p nvim > /dev/null; then diff --git a/install-linux.sh b/install-linux.sh index 934bd47..0406ba2 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -132,8 +132,8 @@ if [ -d ~/.config/blender/3.6 ]; then ln -sf $EWCONFIG_ROOT/configs/blender/3.x/ # -- Finalization -- # On systems that need it, configure Gnome -sh ./configs/gnome/gnome-terminal-settings.sh -sh ./configs/gnome/desktop-settings.sh +sh ./configs/gnome/gnome-terminal-settings.sh || true +sh ./configs/gnome/desktop-settings.sh || true # Attempt to force a termux settings reload on Android devices termux-reload-settings || true diff --git a/scripts/tinker b/scripts/tinker new file mode 100755 index 0000000..2cca4a0 --- /dev/null +++ b/scripts/tinker @@ -0,0 +1,11 @@ +#! /bin/bash +# NOTE: This is a script so that we can launch it from a gnome keybind +set -e + +# If PYTHONSTARTUP is not set, we have to set it +if [ -z "$PYTHONSTARTUP" ]; then + export PYTHONSTARTUP="$HOME/.config/ewconfig/configs/python/python_startup.py" +fi + +# Launch python +PYTHON_TINKER_MODE=1 python3 \ No newline at end of file From e7ede8aff43f17b73cec9a13a18c00fe9831590b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 18 Nov 2023 20:37:41 -0500 Subject: [PATCH 250/326] Add a script to fix gitweb last-modified date --- scripts/gitweb-fix-modification-date | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 scripts/gitweb-fix-modification-date diff --git a/scripts/gitweb-fix-modification-date b/scripts/gitweb-fix-modification-date new file mode 100644 index 0000000..5924675 --- /dev/null +++ b/scripts/gitweb-fix-modification-date @@ -0,0 +1,7 @@ +#! /bin/bash +set -e + +LAST_MODIFIED_FILE="$(git rev-parse --git-dir)"/info/web/last-modified + +mkdir -p "$(dirname "$LAST_MODIFIED_FILE")" +git for-each-ref --sort=-authordate --count=1 --format='%(authordate:iso8601)' >"$LAST_MODIFIED_FILE" \ No newline at end of file From af524c263038fe333a0c302c81710690c88e62d0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sat, 18 Nov 2023 20:48:15 -0500 Subject: [PATCH 251/326] Change file mode to executable --- scripts/gitweb-fix-modification-date | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/gitweb-fix-modification-date diff --git a/scripts/gitweb-fix-modification-date b/scripts/gitweb-fix-modification-date old mode 100644 new mode 100755 From a3d7d30bcd6471f8b7697b1e39e21c448733e28e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 19 Nov 2023 13:06:48 -0500 Subject: [PATCH 252/326] Import snippets from VSCode --- configs/Code/User/snippets/json.json | 12 +++++ configs/Code/User/snippets/python.json | 70 ++++++++++++++++++++++++++ configs/Code/User/snippets/rust.json | 31 ++++++++++++ configs/Code/User/snippets/toml.json | 15 ++++++ 4 files changed, 128 insertions(+) create mode 100644 configs/Code/User/snippets/json.json create mode 100644 configs/Code/User/snippets/python.json create mode 100644 configs/Code/User/snippets/rust.json create mode 100644 configs/Code/User/snippets/toml.json diff --git a/configs/Code/User/snippets/json.json b/configs/Code/User/snippets/json.json new file mode 100644 index 0000000..7c23063 --- /dev/null +++ b/configs/Code/User/snippets/json.json @@ -0,0 +1,12 @@ +{ + "Vector3": { + "prefix": "vector3", + "body": [ + "{", + "\t\"x\": $1,", + "\t\"y\": $2,", + "\t\"z\": $3", + "}", + ] + } +} \ No newline at end of file diff --git a/configs/Code/User/snippets/python.json b/configs/Code/User/snippets/python.json new file mode 100644 index 0000000..acd1b1c --- /dev/null +++ b/configs/Code/User/snippets/python.json @@ -0,0 +1,70 @@ +{ + "CLI App Skeleton": { + "prefix": "cli_app", + "body": [ + "import argparse", + "import sys", + "import logging", + "", + "logger = logging.getLogger(__name__)", + "", + "def main() -> int:", + "\t# Handle program arguments", + "\tap = argparse.ArgumentParser(prog='$1', description='$2')", + "\t$3", + "\tap.add_argument('-v', '--verbose', help='Enable verbose logging', action='store_true')" + "\targs = ap.parse_args()", + "", + "\t# Configure logging", + "\tlogging.basicConfig(", + "\t\tlevel=logging.DEBUG if args.verbose else logging.INFO,", + "\t\tformat='%(levelname)s:\t%(message)s',", + "\t)", + "", + "\treturn 0", + "", + "if __name__ == \"__main__\":", + "\tsys.exit(main())" + ] + }, + "Request error handler": { + "prefix": "rerror", + "body": [ + "if int($1.status_code / 100) != 2:", + "\treturn $2" + ] + }, + "Path to the current file": { + "prefix": "__filepath__", + "body": "Path(__file__)" + }, + "Path to the current file's parent directory": { + "prefix": "__filedir__", + "body": "Path(__file__).parent" + }, + "Disable formatting for block": { + "prefix": "nofmt", + "body": [ + "# fmt: off", + "$1", + "# fmt: on", + "$2" + ] + }, + "Import Path from pathlib": { + "prefix": "impath", + "body": "from pathlib import Path" + }, + "Get a logger instance": { + "prefix": "getlogger", + "body": "logger = logging.getLogger(__name__)" + }, + "Import dataclass": { + "prefix":"impdataclass", + "body": "from dataclasses import dataclass, field" + }, + "Import enums": { + "prefix":"impenum", + "body": "from enum import Enum, auto" + } +} \ No newline at end of file diff --git a/configs/Code/User/snippets/rust.json b/configs/Code/User/snippets/rust.json new file mode 100644 index 0000000..6ece974 --- /dev/null +++ b/configs/Code/User/snippets/rust.json @@ -0,0 +1,31 @@ +{ + "Constructor": { + "prefix": "new", + "body": [ + "/// Construct a new $1", + "pub fn new($2) -> Self {", + "\tSelf {", + "\t\t$3", + "\t}", + "}" + ] + }, + "Derive Macro": { + "prefix": "derive", + "body": "#[derive(Debug, $1)]$2" + }, + "Unit Tests": { + "prefix": "cfg: test", + "body": [ + "#[cfg(test)]", + "mod tests {", + "\tuse super::*;", + "\t", + "\t#[test]", + "\tfn test_$1() {", + "\t\t$2", + "\t}", + "}" + ] + } +} \ No newline at end of file diff --git a/configs/Code/User/snippets/toml.json b/configs/Code/User/snippets/toml.json new file mode 100644 index 0000000..be8de87 --- /dev/null +++ b/configs/Code/User/snippets/toml.json @@ -0,0 +1,15 @@ +{ + "Inculde: Serde": { + "prefix": "serde", + "body": [ + "serde = { version = \"^1.0\", features = [\"derive\"] }", + "serde_json = \"^1.0\"" + ] + }, + "Include: Tokio": { + "prefix": "tokio", + "body": [ + "tokio = { version = \"$1\", features = [\"macros\", \"rt-multi-thread\"] }$2" + ] + }, +} \ No newline at end of file From c7894bfa56d61ceb099c1208e28442c205b4731d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 19 Nov 2023 13:20:39 -0500 Subject: [PATCH 253/326] Add a macro to reinstall config from anywhere --- configs/shells/bash/macros.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 2a575d3..d3519ec 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -223,6 +223,18 @@ ewconfig-run() { cd $cwd } +# Re-run the install script from anywhere +ewconfig-reinstall() { + # Require an argument (linux, windows) + if [ $# != 1 ]; then + echo "Usage: ewconfig-reinstall " + return 1 + fi + + # Execute through ewconfig-run + ewconfig-run sh ./install-$1.sh +} + # Define a function to emulate gh gh-emulated() { if [ $# != 3 ]; then From 68cb27acc954472cd9bfbd1dae08fb7633a1056c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 19 Nov 2023 16:21:47 -0500 Subject: [PATCH 254/326] automatically get machines to learn the secondary remote --- install-linux.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/install-linux.sh b/install-linux.sh index 0406ba2..5c258c9 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -10,6 +10,15 @@ if type -p git > /dev/null; then if [ -d "$EWCONFIG_ROOT/.git" ]; then echo "Syncing git submodules..." git submodule update --init --recursive + + # Make sure that the `ewp` upstream exists + if ! git remote | grep -q ewp; then + echo "Adding secondary git remote" + git remote add ewp git://git.ewpratten.com/ewconfig + git remote set-url --push ewp ssh://ewpratten@git.ewpratten.com:/srv/git/ewconfig + echo "Remotes are:" + git remote -v + fi fi fi From 89f89192a961e7f8969cd0ada28cf3157cd82847 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 19 Nov 2023 16:33:52 -0500 Subject: [PATCH 255/326] New remote for windows --- install-windows.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/install-windows.sh b/install-windows.sh index 1332d1e..76f0502 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -6,6 +6,15 @@ export EWCONFIG_ROOT=$(dirname $(readlink -f $0)) echo "Syncing git submodules..." git submodule update --init --recursive +# Make sure that the `ewp` upstream exists +if ! git remote | grep -q ewp; then + echo "Adding secondary git remote" + git remote add ewp git://git.ewpratten.com/ewconfig + git remote set-url --push ewp ssh://ewpratten@git.ewpratten.com:/srv/git/ewconfig + echo "Remotes are:" + git remote -v +fi + # Make sure scripts are all executable chmod +x $EWCONFIG_ROOT/scripts/* chmod +x $EWCONFIG_ROOT/configs/nautilus/scripts/* From 933692bdf3685f0424af2100f1d93b3963daca40 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 19 Nov 2023 16:36:19 -0500 Subject: [PATCH 256/326] use new remote for pulls --- configs/shells/bash/macros.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index d3519ec..db9aef6 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -190,7 +190,7 @@ wg-cat() { ewconfig-pull() { cwd=$(pwd) cd ~/.config/ewconfig - git pull + git pull ewp master cd $cwd } From 1c875b7f21f59c53d05a753fed9869fb54c6c374 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 20 Nov 2023 12:24:45 -0500 Subject: [PATCH 257/326] Add an auto-discovery command to basejump --- scripts/basejump | 2 +- scripts/basejump-discover | 58 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100755 scripts/basejump-discover diff --git a/scripts/basejump b/scripts/basejump index 9f07900..43fd062 100755 --- a/scripts/basejump +++ b/scripts/basejump @@ -12,7 +12,7 @@ def main() -> int: # Handle program arguments ap = argparse.ArgumentParser(prog="basejump") ap.add_argument( - "subcommand", help="The subcommand to run", choices=["init", "fetch"] + "subcommand", help="The subcommand to run", choices=["init", "fetch", "discover"] ) ap.add_argument("arguments", nargs=argparse.REMAINDER) args = ap.parse_args() diff --git a/scripts/basejump-discover b/scripts/basejump-discover new file mode 100755 index 0000000..bde2d45 --- /dev/null +++ b/scripts/basejump-discover @@ -0,0 +1,58 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import subprocess +from pprint import pprint +from pathlib import Path + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="basejump discover", description="Discover repos in a codebase" + ) + ap.add_argument("root_path", help="The root path of the codebase", type=Path) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Find all git repos in the codebase + logger.info(f"Searching for git repos in: {args.root_path}") + repos = [] + for path in args.root_path.rglob(".git"): + repos.append({"path":str(path.parent.absolute())}) + + # For each repo, find the upstream + logger.info("Finding upstream URLs...") + for repo in repos: + # Get the upstream URL + upstream_url = subprocess.run( + ["git", "remote", "get-url", "origin"], + cwd=repo["path"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="utf-8", + ).stdout.strip() + + # Add the upstream URL to the repo config + repo["upstream"] = upstream_url + + # Print the results + logger.info("Found the following repos:") + pprint(repos) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 14614ec75a8bceba52be0d295b30bc6c8f6578b8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 20 Nov 2023 12:40:59 -0500 Subject: [PATCH 258/326] Improve formatting of basejump --- scripts/basejump-discover | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/basejump-discover b/scripts/basejump-discover index bde2d45..e7cfb19 100755 --- a/scripts/basejump-discover +++ b/scripts/basejump-discover @@ -3,6 +3,7 @@ import argparse import sys import logging import subprocess +import json from pprint import pprint from pathlib import Path @@ -49,7 +50,7 @@ def main() -> int: # Print the results logger.info("Found the following repos:") - pprint(repos) + print(json.dumps(repos, indent=4)) return 0 From c39f2222c3e98316b70e9e6dcc4fcf980f78e726 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 20 Nov 2023 14:25:40 -0500 Subject: [PATCH 259/326] SVG to PNG conversion --- configs/shells/bash/macros.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index db9aef6..4a7d0df 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -248,4 +248,13 @@ gh-emulated() { # Only if `gh` is not installed if ! command -v gh &> /dev/null; then alias gh=gh-emulated -fi \ No newline at end of file +fi + +# Convert an SVG to a PNG +svg2png() { + if [ $# != 1 ]; then + echo "Usage: svg2png " + else + inkscape -z "$1.png" "$1" --export-type=png + fi +} From df33d0117bb8411298c215826d25323ee5d8a770 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Nov 2023 09:48:10 -0500 Subject: [PATCH 260/326] Add some shorthands to git --- configs/git/.gitconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index c341b18..236866e 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -25,7 +25,10 @@ lscommits = ! ( echo -e "Commits\tFile" && git log --pretty=format: --name-only | sed '/^$/d' | sort | uniq -c | sort -g -r ) | less lsc = lscommits diff-against = diff --merge-base - fix-recreated-branch = reset --hard @{u} + fix-recreated-branch = reset --hard @{u} + fa = fetch --all + c = commit + aa = add . [filter "lfs"] clean = git-lfs clean -- %f From 1ecbc07ffbb513261d568f83ba61cf3f9ad0586d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Nov 2023 10:06:11 -0500 Subject: [PATCH 261/326] Add `pull --all` macro --- configs/git/.gitconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 236866e..57f4a36 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -27,6 +27,7 @@ diff-against = diff --merge-base fix-recreated-branch = reset --hard @{u} fa = fetch --all + pa = pull --all c = commit aa = add . From 93710f159c96118049be7a8008a07e223308ac4c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Nov 2023 11:09:41 -0500 Subject: [PATCH 262/326] Add vim support to windows --- install-windows.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/install-windows.sh b/install-windows.sh index 76f0502..a835325 100644 --- a/install-windows.sh +++ b/install-windows.sh @@ -45,6 +45,9 @@ ln -sf $EWCONFIG_ROOT/configs/git/.gitconfig ~/.gitconfig ln -sf $EWCONFIG_ROOT/configs/sssh/allowed_signers ~/.ssh/allowed_signers || true ln -sf $EWCONFIG_ROOT/configs/git/.mailmap ~/.config/git/.mailmap +# Configure Vim +ln -sf $EWCONFIG_ROOT/configs/vim/.vimrc ~/.vimrc + # Remove Microsoft's fake python executables rm $LOCALAPPDATA/Microsoft/WindowsApps/python.exe || true rm $LOCALAPPDATA/Microsoft/WindowsApps/python3.exe || true From 08d1b84c47b642e8b696670a97b1c46a7d8d2961 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Nov 2023 11:12:34 -0500 Subject: [PATCH 263/326] Improve how badly spelled words are rendered --- configs/vim/.vimrc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/configs/vim/.vimrc b/configs/vim/.vimrc index 8e14521..275dd4a 100644 --- a/configs/vim/.vimrc +++ b/configs/vim/.vimrc @@ -56,9 +56,15 @@ if !exists('g:vscode') set spell set spelllang=en_ca,en_us set spelloptions=camel + + " Hide spellcheck highlights I don't care about hi clear SpellCap hi clear SpellRare + " Change the spellcheck highlight to an underline + hi clear SpellBad + hi SpellBad cterm=underline ctermfg=DarkRed + " Disable spellcheck for some file formats autocmd FileType man setlocal nospell autocmd FileType diff setlocal nospell @@ -71,4 +77,4 @@ hi DiffFile ctermfg=White ctermbg=none cterm=bold hi DiffIndexLine ctermfg=White ctermbg=none cterm=bold hi DiffAdd ctermfg=DarkGreen ctermbg=none hi DiffChange ctermfg=DarkRed ctermbg=none -hi DiffDelete ctermfg=DarkRed ctermbg=none \ No newline at end of file +hi DiffDelete ctermfg=DarkRed ctermbg=none From f453d5b33e3d6c4d488c4df72e7afb8f73ecb93b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Nov 2023 12:32:06 -0500 Subject: [PATCH 264/326] Add some unicode snippets --- .../Code/User/snippets/Unicode.code-snippets | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 configs/Code/User/snippets/Unicode.code-snippets diff --git a/configs/Code/User/snippets/Unicode.code-snippets b/configs/Code/User/snippets/Unicode.code-snippets new file mode 100644 index 0000000..92e6fd3 --- /dev/null +++ b/configs/Code/User/snippets/Unicode.code-snippets @@ -0,0 +1,195 @@ +{ + // Symbols + "Unicode: PI": { + "prefix": "uni_pi", + "body": "π" + }, + "Unicode: Infinity": { + "prefix": "uni_infinity", + "body": "∞" + }, + "Unicode: Square Root": { + "prefix": "uni_sqrt", + "body": "√" + }, + "Unicode: Real": { + "prefix": "uni_real", + "body": "ℝ" + }, + "Unicode: Natural": { + "prefix": "uni_natural", + "body": "ℕ" + }, + "Unicode: Integer": { + "prefix": "uni_integer", + "body": "ℤ" + }, + "Unicode: Rational": { + "prefix": "uni_rational", + "body": "ℚ" + }, + "Unicode: Complex": { + "prefix": "uni_complex", + "body": "ℂ" + }, + "Unicode: Plus or Minus": { + "prefix": "uni_plus_minus", + "body": "±" + }, + "Unicode: Squared": { + "prefix": "uni_squared", + "body": "²" + }, + "Unicode: Cubed": { + "prefix": "uni_cubed", + "body": "³" + }, + "Unicode: Hypercubed": { + "prefix": "uni_hypercubed", + "body": "⁴" + }, + "Unicode: Degree": { + "prefix": "uni_degree", + "body": "°" + }, + "Unicode: Half": { + "prefix": "uni_half", + "body": "½" + }, + "Unicode: Third": { + "prefix": "uni_third", + "body": "⅓" + }, + "Unicode: Two Thirds": { + "prefix": "uni_two_thirds", + "body": "⅔" + }, + "Unicode: Quarter": { + "prefix": "uni_quarter", + "body": "¼" + }, + "Unicode: Three Quarters": { + "prefix": "uni_three_quarters", + "body": "¾" + }, + + // Equality + "Unicode: Not Equal To": { + "prefix": "uni_neq", + "body": "≠" + }, + "Unicode: Approximately Equal To": { + "prefix": "uni_approx", + "body": "≈" + }, + "Unicode: Greater Than or Equal To": { + "prefix": "uni_gte", + "body": "≥" + }, + "Unicode: Less Than or Equal To": { + "prefix": "uni_lte", + "body": "≤" + }, + + // Set Operations + "Unicode: Union": { + "prefix": "uni_union", + "body": "∪" + }, + "Unicode: Intersection": { + "prefix": "uni_intersect", + "body": "∩" + }, + "Unicode: Element Of": { + "prefix": "uni_element", + "body": "∈" + }, + "Unicode: Not Element Of": { + "prefix": "uni_not_element", + "body": "∉" + }, + "Unicode: Subset Of": { + "prefix": "uni_subset", + "body": "⊂" + }, + "Unicode: Superset Of": { + "prefix": "uni_superset", + "body": "⊃" + }, + "Unicode: Subset Of or Equal To": { + "prefix": "uni_subset_eq", + "body": "⊆" + }, + "Unicode: Superset Of or Equal To": { + "prefix": "uni_superset_eq", + "body": "⊇" + }, + "Unicode: Empty Set": { + "prefix": "uni_empty", + "body": "∅" + }, + + // Vectors + "Unicode: Vector Multiplication": { + "prefix": "uni_vector_mult", + "body": "⋅" + }, + "Unicode: Vector Cross Product": { + "prefix": "uni_vector_cross", + "body": "×" + }, + "Unicode: Vector Dot Product": { + "prefix": "uni_vector_dot", + "body": "·" + }, + "Unicode: Vector Diacritic": { + "prefix": "uni_vector", + "body": "$1\u20D7$2" + }, + "Unicode: Unit Vector Diacritic": { + "prefix": "uni_hat", + "body": "$1\u0302$2" + }, + + // Arrows + "Unicode: Left Arrow": { + "prefix": "uni_left_arrow", + "body": "←" + }, + "Unicode: Right Arrow": { + "prefix": "uni_right_arrow", + "body": "→" + }, + "Unicode: Up Arrow": { + "prefix": "uni_up_arrow", + "body": "↑" + }, + "Unicode: Down Arrow": { + "prefix": "uni_down_arrow", + "body": "↓" + }, + "Unicode: Left Right Arrow": { + "prefix": "uni_left_right_arrow", + "body": "↔" + }, + "Unicode: Up Down Arrow": { + "prefix": "uni_up_down_arrow", + "body": "↕" + }, + "Unicode: Top Left Arrow": { + "prefix": "uni_top_left_arrow", + "body": "↖" + }, + "Unicode: Top Right Arrow": { + "prefix": "uni_top_right_arrow", + "body": "↗" + }, + "Unicode: Bottom Right Arrow": { + "prefix": "uni_bottom_right_arrow", + "body": "↘" + }, + "Unicode: Bottom Left Arrow": { + "prefix": "uni_bottom_left_arrow", + "body": "↙" + }, +} \ No newline at end of file From 1b5c305a22522f5605e7da8adafbb31c8bc5f7ad Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Nov 2023 12:42:02 -0500 Subject: [PATCH 265/326] improve python snippets --- configs/Code/User/snippets/python.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/configs/Code/User/snippets/python.json b/configs/Code/User/snippets/python.json index acd1b1c..a60028e 100644 --- a/configs/Code/User/snippets/python.json +++ b/configs/Code/User/snippets/python.json @@ -56,15 +56,19 @@ "body": "from pathlib import Path" }, "Get a logger instance": { - "prefix": "getlogger", - "body": "logger = logging.getLogger(__name__)" + "prefix": "logger", + "body": "logger = logging.getLogger(${1|__name__,'werkzeug'|})" }, "Import dataclass": { "prefix":"impdataclass", - "body": "from dataclasses import dataclass, field" + "body": "from dataclasses import dataclass${1:, field}" + }, + "Import datetime": { + "prefix":"impdatetime", + "body": "from datetime import datetime" }, "Import enums": { "prefix":"impenum", - "body": "from enum import Enum, auto" + "body": "from enum import Enum${1:, auto}" } } \ No newline at end of file From 27466fa20efb36ada09d8670fdd7595591aa2e29 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 21 Nov 2023 19:07:31 -0500 Subject: [PATCH 266/326] add 6421 --- configs/Code/User/snippets/Unicode.code-snippets | 4 ++++ configs/ssh/config | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configs/Code/User/snippets/Unicode.code-snippets b/configs/Code/User/snippets/Unicode.code-snippets index 92e6fd3..cde4a05 100644 --- a/configs/Code/User/snippets/Unicode.code-snippets +++ b/configs/Code/User/snippets/Unicode.code-snippets @@ -48,6 +48,10 @@ "prefix": "uni_hypercubed", "body": "⁴" }, + "Unicode: Power of N": { + "prefix": "uni_power_n", + "body": "ⁿ" + }, "Unicode: Degree": { "prefix": "uni_degree", "body": "°" diff --git a/configs/ssh/config b/configs/ssh/config index 4758a3c..8bbea8b 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -70,7 +70,7 @@ Host *.ring.nlnog.net # SDF.org Host sdf.org *.sdf.org - user ewpratten + User ewpratten Host sdf HostName sdf.org Host otaku @@ -81,6 +81,8 @@ Host *.gurustudio.com User "guru-domain\\epratten" Host td-prod td-prod2 td-prod3 td-prod4 User guru +Host w6421 + User "guru-domain\\epratten" # Personal Infra Host oci-arm From cfcdd908b641348b1dd3794444512593b69ac7b8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 22 Nov 2023 10:16:42 -0500 Subject: [PATCH 267/326] Move nvim-only keybinds to correct config --- configs/nvim/init.vim | 5 +++++ configs/vim/.vimrc | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 60e7b49..8347f88 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -30,6 +30,11 @@ endif " Enable Leap lua require('leap').add_default_mappings() +" VSCode-style comment toggling +nnoremap :Commentary +vnoremap :Commentary +inoremap :Commentary + " Custom functions function! MkdirAndWrite() let dir = expand('%:p:h') diff --git a/configs/vim/.vimrc b/configs/vim/.vimrc index 275dd4a..73ea498 100644 --- a/configs/vim/.vimrc +++ b/configs/vim/.vimrc @@ -27,11 +27,6 @@ inoremap inoremap lcw nnoremap cwl -" VSCode-style comment toggling -nnoremap :Commentary -vnoremap :Commentary -inoremap :Commentary - " Force VIM to use system clipboard set clipboard=unnamedplus From 2622ac9c4387c5d0e8a6af3c9af4be60f0edad59 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 22 Nov 2023 11:46:33 -0500 Subject: [PATCH 268/326] Add a meme generator --- README.md | 2 + configs/memegen/fonts/impact.ttf | Bin 0 -> 136076 bytes .../templates/bernie-asking/config.json | 17 ++ .../templates/bernie-asking/template.png | Bin 0 -> 424076 bytes install-linux.sh | 3 + scripts/memegen | 226 ++++++++++++++++++ 6 files changed, 248 insertions(+) create mode 100644 configs/memegen/fonts/impact.ttf create mode 100644 configs/memegen/templates/bernie-asking/config.json create mode 100644 configs/memegen/templates/bernie-asking/template.png create mode 100755 scripts/memegen diff --git a/README.md b/README.md index 050cf3f..c459a12 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ This repository stores most of my common config files. It is designed to be deployable to pretty much any system. Assuming ideal conditions, any machine is one `sh ./install-` away from behaving like my personal workstation. +*I know its called ew**config**, but at this point, its more of a monorepo of scripts* + ## Setup The scripts in this repository have the following dependencies: diff --git a/configs/memegen/fonts/impact.ttf b/configs/memegen/fonts/impact.ttf new file mode 100644 index 0000000000000000000000000000000000000000..114e6c1968b663086409144e50e7a592bff1d6c2 GIT binary patch literal 136076 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 VQlm?y$QD;A35 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 literal 0 HcmV?d00001 diff --git a/configs/memegen/templates/bernie-asking/config.json b/configs/memegen/templates/bernie-asking/config.json new file mode 100644 index 0000000..5a2f0f4 --- /dev/null +++ b/configs/memegen/templates/bernie-asking/config.json @@ -0,0 +1,17 @@ +{ + "font": "impact.ttf", + "fill_color": [255, 255, 255], + "stroke_color": [0, 0, 0], + "stroke_width": 2, + "zones": { + "bottom": { + "horizontal_align": "center", + "horizontal_offset": 0, + "vertical_align": "bottom", + "vertical_offset": -50, + "width": "80%", + "max_line_height": 50, + "line_spacing": 5 + } + } +} \ No newline at end of file diff --git a/configs/memegen/templates/bernie-asking/template.png b/configs/memegen/templates/bernie-asking/template.png new file mode 100644 index 0000000000000000000000000000000000000000..0d19bb42a29cb4efc9b844e06b87048276253c66 GIT binary patch literal 424076 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� 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

0Dw$w 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
  • 5Qebba0wg#ZxH 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

    D}C@ovTxGS6_E|GhD2t+R3 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 List[str]: + # Find all directories in the templates directory + return [p.name for p in (CONFIG_DIR / "templates").glob("*") if p.is_dir()] + + +def load_template(name: str) -> MemeTemplate: + logger.info(f"Loading template: {name}") + + # Find the template directory + template_dir = CONFIG_DIR / "templates" / name + if not template_dir.exists(): + logger.error(f"Template {name} does not exist") + sys.exit(1) + + return MemeTemplate( + image_path=template_dir / "template.png", + config=json.loads((template_dir / "config.json").read_text()), + ) + + +def calc_width_from_image(width_str: str, image_width: int) -> int: + if width_str.endswith("%"): + return int(image_width * int(width_str[:-1]) / 100) + else: + return int(width_str) + + +def render_text_on_image(image: Image, text: str, zone: str, config: Dict[str, Any]): + # NOTE: This must handle text with newlines + # Get the zone config + zone_config = config["zones"][zone] + horizontal_alignment = HorizontalAlignment(zone_config["horizontal_align"]) + vertical_alignment = VerticalAlignment(zone_config["vertical_align"]) + text_width = calc_width_from_image(zone_config["width"], image.width) + max_line_height = zone_config["max_line_height"] + font_path = CONFIG_DIR / "fonts" / config["font"] + + # Create the font + font = None + font_size = 1 + while True: + font = ImageFont.truetype(str(font_path), font_size) + + # Split the text into lines + lines = text.splitlines() + bounding_boxes = [] + for line in lines: + bounding_boxes.append(font.getbbox(line)) + + # Calculate the height of the text + line_height = max([bbox[3] for bbox in bounding_boxes]) + total_height = sum( + [bbox[3] + zone_config["line_spacing"] for bbox in bounding_boxes] + ) + max_width = max([bbox[2] for bbox in bounding_boxes]) + + # If we have a max line height, ensure we don't exceed it + if max_line_height and line_height > max_line_height: + font_size -= 1 + break + + # Don't exceed the width + if max_width > text_width: + font_size -= 1 + break + + # Increment the font size + font_size += 1 + + # Determine the starting Y position + y = zone_config["vertical_offset"] + if vertical_alignment == VerticalAlignment.CENTER: + y += (image.height - total_height) / 2 + elif vertical_alignment == VerticalAlignment.BOTTOM: + y += image.height - total_height + + # Render each line onto the image + draw = ImageDraw.Draw(image) + for line in text.splitlines(): + # Calculate the x position + if horizontal_alignment == HorizontalAlignment.LEFT: + x = zone_config["horizontal_offset"] + elif horizontal_alignment == HorizontalAlignment.CENTER: + x = ((image.width - font.getbbox(line)[2]) / 2) + zone_config[ + "horizontal_offset" + ] + elif horizontal_alignment == HorizontalAlignment.RIGHT: + x = (image.width - font.getbbox(line)[2]) + zone_config["horizontal_offset"] + else: + raise ValueError(f"Invalid horizontal alignment: {horizontal_alignment}") + + # Render the text + draw.text( + (x, y), + line, + fill=tuple(config["fill_color"]), + stroke_fill=tuple(config["stroke_color"]), + stroke_width=config["stroke_width"], + font=font, + ) + + # Increment the y position + y += line_height + zone_config["line_spacing"] + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog="memegen", description="Generates memes") + ap.add_argument( + "template", help="The template to use", choices=discover_templates() + ) + ap.add_argument("--top-text", help="Top text (if applicable)") + ap.add_argument("--bottom-text", help="Bottom text (if applicable)") + ap.add_argument( + "--keep-case", help="Keep the case of the text", action="store_true" + ) + ap.add_argument("--output", "-o", help="Output file path") + ap.add_argument("--show", help="Show the image after creation", action="store_true") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Load the template + template = load_template(args.template) + template_supports_top_text = "top" in template.config["zones"] + template_supports_bottom_text = "bottom" in template.config["zones"] + + # Ensure we have text + if args.top_text and not template_supports_top_text: + logger.error(f"Template {args.template} does not support top text") + sys.exit(1) + if args.bottom_text and not template_supports_bottom_text: + logger.error(f"Template {args.template} does not support bottom text") + sys.exit(1) + if not args.top_text and not args.bottom_text: + logger.error("No text provided") + if not all([template_supports_top_text, template_supports_bottom_text]): + required_text = "top" if template_supports_top_text else "bottom" + logger.error( + f"Template {args.template} requires the --{required_text}-text argument" + ) + sys.exit(1) + + # Transform the text + # fmt:off + top_text = args.top_text.upper() if args.top_text and (not args.keep_case) else args.top_text + bottom_text = args.bottom_text.upper() if args.bottom_text and (not args.keep_case) else args.bottom_text + top_text = top_text.replace("\\n", "\n").replace("\\N", "\n") if top_text else None + bottom_text = bottom_text.replace("\\n", "\n").replace("\\N", "\n") if bottom_text else None + # fmt: on + + # Load the image + image = Image.open(template.image_path) + + # Render the text + if top_text: + render_text_on_image(image, top_text, "top", template.config) + if bottom_text: + render_text_on_image(image, bottom_text, "bottom", template.config) + + # Build the output path + output_path = ( + Path(args.output) + if args.output + else ( + DEFAULT_OUTPUT_DIR + / f"{args.template}-{datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.png" + ) + ) + output_path.parent.mkdir(parents=True, exist_ok=True) + + # Save the image + image.save(output_path) + + # Show the image + if args.show: + subprocess.run(["xdg-open", str(output_path)]) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 74edb650f698a9dbf21f9b2e1db0e7c4e6f116be Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 22 Nov 2023 12:05:30 -0500 Subject: [PATCH 269/326] Add hotline bling and megamind memes --- .../templates/hotline-bling/config.json | 34 ++++++++++++++++++ .../templates/hotline-bling/template.png | Bin 0 -> 109917 bytes .../memegen/templates/megamind/config.json | 17 +++++++++ .../memegen/templates/megamind/template.png | Bin 0 -> 170503 bytes scripts/memegen | 6 ++-- 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 configs/memegen/templates/hotline-bling/config.json create mode 100644 configs/memegen/templates/hotline-bling/template.png create mode 100644 configs/memegen/templates/megamind/config.json create mode 100644 configs/memegen/templates/megamind/template.png diff --git a/configs/memegen/templates/hotline-bling/config.json b/configs/memegen/templates/hotline-bling/config.json new file mode 100644 index 0000000..cded53e --- /dev/null +++ b/configs/memegen/templates/hotline-bling/config.json @@ -0,0 +1,34 @@ +{ + "font": "impact.ttf", + "fill_color": [ + 0, + 0, + 0 + ], + "stroke_color": [ + 0, + 0, + 0 + ], + "stroke_width": 0, + "zones": { + "top": { + "horizontal_align": "right", + "horizontal_offset": -5, + "vertical_align": "top", + "vertical_offset": 75, + "width": "45%", + "max_line_height": 50, + "line_spacing": 5 + }, + "bottom": { + "horizontal_align": "right", + "horizontal_offset": -5, + "vertical_align": "bottom", + "vertical_offset": -75, + "width": "45%", + "max_line_height": 50, + "line_spacing": 5 + } + } +} \ No newline at end of file diff --git a/configs/memegen/templates/hotline-bling/template.png b/configs/memegen/templates/hotline-bling/template.png new file mode 100644 index 0000000000000000000000000000000000000000..7002060214c74b120b386e29dc53623896f46e39 GIT binary patch literal 109917 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

    qED3P~oAS(K;rW%a;~<^LYrHa@ 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
    @%d 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 !1wkS1e{4Ud>CK0e)L###d2{0rN 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 DSHPxA literal 0 HcmV?d00001 diff --git a/scripts/memegen b/scripts/memegen index 678bd81..ae77f67 100755 --- a/scripts/memegen +++ b/scripts/memegen @@ -151,7 +151,7 @@ def main() -> int: "--keep-case", help="Keep the case of the text", action="store_true" ) ap.add_argument("--output", "-o", help="Output file path") - ap.add_argument("--show", help="Show the image after creation", action="store_true") + ap.add_argument("--no-show", help="Don't show the image after creation", action="store_true") ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) @@ -207,7 +207,7 @@ def main() -> int: if args.output else ( DEFAULT_OUTPUT_DIR - / f"{args.template}-{datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.png" + / f"meme-{datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.{args.template}.png" ) ) output_path.parent.mkdir(parents=True, exist_ok=True) @@ -216,7 +216,7 @@ def main() -> int: image.save(output_path) # Show the image - if args.show: + if not args.no_show: subprocess.run(["xdg-open", str(output_path)]) return 0 From a310c354f73ce390166996660134e7ff9a199589 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 27 Nov 2023 16:39:27 -0500 Subject: [PATCH 270/326] Add a script to handle fetching blink images --- scripts/blink-fetch | 110 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100755 scripts/blink-fetch diff --git a/scripts/blink-fetch b/scripts/blink-fetch new file mode 100755 index 0000000..4c6802b --- /dev/null +++ b/scripts/blink-fetch @@ -0,0 +1,110 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import getpass +import asyncio +import exif +from datetime import datetime +from blinkpy.blinkpy import Blink +from blinkpy.auth import Auth +from blinkpy.helpers.util import json_load +from pathlib import Path + +logger = logging.getLogger(__name__) + +def decdeg2dms(dd): + mult = -1 if dd < 0 else 1 + mnt,sec = divmod(abs(dd)*3600, 60) + deg,mnt = divmod(mnt, 60) + return mult*deg, mult*mnt, mult*sec + +async def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="blink-fetch", description="Fetch an image from a Blink camera" + ) + ap.add_argument("--username", help="Blink username", required=True) + ap.add_argument("--password", help="Blink password") + ap.add_argument("--camera-id", help="Camera ID", default="155295") + ap.add_argument("--output-dir", help="Output directory", default="/tmp/blink") + ap.add_argument("--no-2fa", help="Don't try to get 2FA credentials", action="store_true") + ap.add_argument("--no-exif", help="Don't write EXIF data", action="store_true") + ap.add_argument("--exif-camera", help="Camera name", default="Blink Mini") + ap.add_argument("--exif-latitude", "--exif-lat", help="Camera latitude (Decimal Degrees)") + ap.add_argument("--exif-longitude", "--exif-lng", help="Camera longitude (Decimal Degrees)") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Ask for the password if it wasn't provided + if args.password is None: + args.password = getpass.getpass(prompt="Blink Password: ") + + # Authenticate with Blink servers + auth = Auth({"username": args.username, "password": args.password}, no_prompt=args.no_2fa) + blink = Blink() + blink.auth = auth + await blink.start() + + # Find the requested camera + for name, camera in blink.cameras.items(): + logger.debug(f"Found camera: {name} ({camera.attributes['camera_id']})") + if camera.attributes["camera_id"] == args.camera_id: + logger.info("Found requested camera") + break + else: + logger.error("Could not find requested camera") + return 1 + + # Fetch the image + logger.info("Fetching image") + await camera.snap_picture() + await blink.refresh() + + # Create the output directory if it doesn't exist + now = datetime.now() + out_file = Path( + f"{args.output_dir}/camera_{args.camera_id}.{now.strftime('%Y%m%d_%H%M%S')}.jpg" + ) + out_file.parent.mkdir(parents=True, exist_ok=True) + + logger.info(f"Writing image to: {out_file}") + await camera.image_to_file(str(out_file)) + + # Handle EXIF data + if not args.no_exif: + logger.info("Re-reading image to inject EXIF data") + with open(out_file, "rb") as f: + image = exif.Image(f) + + # Set the camera type + image.model = args.exif_camera + + # If the user provided a latitude and longitude, set it + # if args.exif_latitude and args.exif_longitude: + # image.gps_latitude = decdeg2dms(float(args.exif_latitude)) + # image.gps_longitude = decdeg2dms(float(args.exif_longitude)) + # image.gps_latitude_ref = "N" + # image.gps_longitude_ref = "W" + + # Set the timestamp + image.datetime_original = now.strftime(exif.DATETIME_STR_FORMAT) + + # Write the EXIF data back to the file + logger.info("Writing EXIF data") + with open(out_file, "wb") as f: + f.write(image.get_file()) + + return 0 + + +if __name__ == "__main__": + sys.exit(asyncio.run(main())) From c128fddd5152f9462bf0ffc158c51288f6b86de8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 27 Nov 2023 16:41:07 -0500 Subject: [PATCH 271/326] Default to py3 --- scripts/blink-fetch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/blink-fetch b/scripts/blink-fetch index 4c6802b..2eda59e 100755 --- a/scripts/blink-fetch +++ b/scripts/blink-fetch @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 import argparse import sys import logging From 15a376416bc0c3c1e83480ed487862a772d83b52 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 27 Nov 2023 16:54:37 -0500 Subject: [PATCH 272/326] Add a timelapse script --- scripts/blink-fetch | 1 + scripts/blink-timelapse | 84 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100755 scripts/blink-timelapse diff --git a/scripts/blink-fetch b/scripts/blink-fetch index 2eda59e..31d9312 100755 --- a/scripts/blink-fetch +++ b/scripts/blink-fetch @@ -1,4 +1,5 @@ #! /usr/bin/env python3 +# Installation: pip install exif asyncio blinkpy import argparse import sys import logging diff --git a/scripts/blink-timelapse b/scripts/blink-timelapse new file mode 100755 index 0000000..a1e0c4a --- /dev/null +++ b/scripts/blink-timelapse @@ -0,0 +1,84 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import subprocess +from datetime import datetime +from pathlib import Path + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="blink-timelapse", + description="Generates timelapses from blink image captures", + ) + ap.add_argument("--camera-id", help="Camera ID", default="155295") + ap.add_argument("--image-dir", help="Image directory", default="/tmp/blink") + ap.add_argument( + "--output-dir", help="Output directory", default="~/Videos/BlinkTimelapse" + ) + ap.add_argument( + "--delete-frames", help="Delete frames after processing", action="store_true" + ) + ap.add_argument("--frame-rate", help="Frame rate", default="5") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Find all frames + frames = Path(args.image_dir).expanduser().glob(f"camera_{args.camera_id}.*.jpg") + frames = sorted(frames, key=lambda frame: frame.stat().st_mtime) + logger.info(f"Found {len(frames)} frames") + logger.info( + f"Oldest frame is from: {datetime.fromtimestamp(frames[0].stat().st_mtime)}" + ) + logger.info( + f"Newest frame is from: {datetime.fromtimestamp(frames[-1].stat().st_mtime)}" + ) + + # Create output directory + output_dir = Path(args.output_dir).expanduser() + output_file = output_dir / f"camera_{args.camera_id}.{datetime.now().strftime('%Y%m%d-%H%M%S')}.mp4" + output_dir.mkdir(parents=True, exist_ok=True) + + # Generate timelapse + logger.info(f"Generating timelapse: {output_file}") + subprocess.run( + [ + "ffmpeg", + "-r", + args.frame_rate, + "-pattern_type", + "glob", + "-i", + f"{args.image_dir}/camera_{args.camera_id}.*.jpg", + "-c:v", + "libx264", + "-pix_fmt", + "yuv420p", + str(output_file), + ], + check=True, + ) + + # Delete frames if needed + if args.delete_frames: + logger.info("Deleting frames") + for frame in frames: + frame.unlink() + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 0dfe5f3ab66df02b30c4fe0bce1337c55e7c7e8d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 28 Nov 2023 12:47:12 -0500 Subject: [PATCH 273/326] Add a script to check blink frames on a remote server --- scripts/blink-check | 101 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100755 scripts/blink-check diff --git a/scripts/blink-check b/scripts/blink-check new file mode 100755 index 0000000..af9eef4 --- /dev/null +++ b/scripts/blink-check @@ -0,0 +1,101 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import subprocess +from datetime import datetime + +logger = logging.getLogger(__name__) + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog='blink-check', description='Check on a running blink-fetch cron task') + ap.add_argument("hostname", help="[user@]hostname[:port] for SSH") + ap.add_argument("--image-dir", help="Remote directory containing fetched images", default="/tmp/blink") + ap.add_argument("--camera-id", help="Camera ID", default="155295") + ap.add_argument("--show-latest", "--show", "-s", help="Download and display the latest image (if possible)", action="store_true") + ap.add_argument('-v', '--verbose', help='Enable verbose logging', action='store_true') + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format='%(levelname)s: %(message)s', + ) + + # List files in image directory + logger.info(f"Listing files in: {args.hostname}:{args.image_dir}") + result = subprocess.run( + [ + "ssh", + args.hostname, + "ls", + "-1", + args.image_dir, + ], + capture_output=True, + text=True, + ) + + # Check for errors + if result.returncode != 0: + logger.error(f"Failed to list files in: {args.hostname}:{args.image_dir}") + logger.error(result.stderr) + return 1 + + # Find all frames + frames = result.stdout.splitlines() + frames = [frame for frame in frames if frame.startswith(f"camera_{args.camera_id}.")] + frames = sorted(frames) + logger.info(f"Found {len(frames)} frames") + if len(frames) > 0: + oldest_frame_time = datetime.strptime(frames[0].split('.')[1], "%Y%m%d_%H%M%S") + newest_frame_time = datetime.strptime(frames[-1].split('.')[1], "%Y%m%d_%H%M%S") + logger.info(f"Oldest frame is from: {oldest_frame_time}") + logger.info(f"Newest frame is from: {newest_frame_time}") + + # Download and display the latest image + if args.show_latest: + if len(frames) > 0: + latest_frame = frames[-1] + logger.info(f"Downloading latest frame: {latest_frame}") + result = subprocess.run( + [ + "scp", + f"{args.hostname}:{args.image_dir}/{latest_frame}", + "/tmp/blink-latest.jpg", + ], + capture_output=True, + text=True, + ) + + # Check for errors + if result.returncode != 0: + logger.error(f"Failed to download latest frame: {latest_frame}") + logger.error(result.stderr) + return 1 + + # Display image + logger.info(f"Displaying latest frame: {latest_frame}") + result = subprocess.run( + [ + "xdg-open", + "/tmp/blink-latest.jpg", + ], + capture_output=True, + text=True, + ) + + # Check for errors + if result.returncode != 0: + logger.error(f"Failed to display latest frame: {latest_frame}") + logger.error(result.stderr) + return 1 + else: + logger.info(f"No frames to display") + + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file From c36a358c1256d11e7ee1545459322f7c1b0b0792 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 28 Nov 2023 14:03:43 -0500 Subject: [PATCH 274/326] Script to upload files to google photos --- scripts/gp-upload | 217 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100755 scripts/gp-upload diff --git a/scripts/gp-upload b/scripts/gp-upload new file mode 100755 index 0000000..7cd8e8d --- /dev/null +++ b/scripts/gp-upload @@ -0,0 +1,217 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import requests +import socket +import urllib.parse +from pathlib import Path + +logger = logging.getLogger(__name__) + +G_CLIENT_ID = "107923498573-ruh1uhkfe1t5f18vam6sckq7pqer1vmg.apps.googleusercontent.com" +G_SCOPES = ["https://www.googleapis.com/auth/photoslibrary.appendonly"] +G_REDIRECT_URI = "http://localhost:7842" + + +def get_google_oauth_token() -> str: + """Either log the user in, or used a stored refresh token to get an OAuth token""" + refresh_token_path = Path("~/.config/gp-upload/refresh-token").expanduser() + client_secret_path = Path("~/.config/gp-upload/client-secret").expanduser() + + # Read the client secret + with client_secret_path.open("r") as f: + client_secret = f.read().strip() + + # Check if we have a refresh token + if refresh_token_path.exists(): + logger.info("Using stored refresh token") + + # Read the refresh token + with refresh_token_path.open("r") as f: + refresh_token = f.read().strip() + + # Make the request + response = requests.post( + "https://oauth2.googleapis.com/token", + data={ + "client_id": G_CLIENT_ID, + "grant_type": "refresh_token", + "refresh_token": refresh_token, + "client_secret": client_secret, + }, + ) + + # Check for errors + if response.status_code != 200: + logger.error("Failed to get OAuth token") + logger.error(response.text) + return None + + # Return the OAuth token + return response.json()["access_token"] + + # Otherwise, log the user in + else: + logger.info("Logging user in") + + # Direct the user to Google's login page + logger.info("Please visit the following URL to log in:") + logger.info( + f"https://accounts.google.com/o/oauth2/v2/auth?client_id={G_CLIENT_ID}&response_type=code&scope={'+'.join(G_SCOPES)}&redirect_uri={G_REDIRECT_URI}&access_type=offline&prompt=consent" + ) + + # Open a TCP server to listen for the redirect + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind(("localhost", 7842)) + s.listen() + + # Wait for the redirect + conn, addr = s.accept() + with conn: + # Read the request + request = conn.recv(1024).decode("utf-8") + + # Parse the request + request = request.splitlines() + request = [line for line in request if line.startswith("GET")] + request = request[0].split(" ")[1] + request = request.split("?")[1] + request = request.split("&") + request = {key: urllib.parse.unquote(value) for key, value in [pair.split("=") for pair in request]} + + # Check for errors + if "error" in request: + logger.error(f"Failed to log in: {request['error']}") + conn.sendall(b"HTTP/1.1 500 Internal Server Error\n\n

    Failed to log in

    ") + conn.close() + return None + + # Return a message to the user and close the socket + conn.sendall(b"HTTP/1.1 200 OK\n\n

    Success!

    ") + conn.close() + + # Make the request + response = requests.post( + "https://oauth2.googleapis.com/token", + data={ + "client_id": G_CLIENT_ID, + "code": request["code"], + "grant_type": "authorization_code", + "redirect_uri": G_REDIRECT_URI, + "client_secret": client_secret, + }, + ) + logger.info(f"Response: {response.text}") + + # Check for errors + if response.status_code != 200: + logger.error("Failed to get OAuth token") + logger.error(response.text) + return None + access_token = response.json()["access_token"] + refresh_token = response.json()["refresh_token"] + + # Save the refresh token + refresh_token_path.parent.mkdir(parents=True, exist_ok=True) + with refresh_token_path.open("w") as f: + f.write(refresh_token) + + # Return the OAuth token + return access_token + + + +def upload_file(file: Path, oauth_token: str): + # Read the file + with file.open("rb") as f: + file_data = f.read() + + # Make the upload request + logger.info("Creating new upload") + response = requests.post( + "https://photoslibrary.googleapis.com/v1/uploads", + headers={ + "Authorization": f"Bearer {oauth_token}", + "Content-type": "application/octet-stream", + "X-Goog-Upload-File-Name": file.name, + "X-Goog-Upload-Protocol": "raw", + }, + data=file_data, + ) + logger.info(f"Uploaded {file.stat().st_size} bytes") + + # Check for errors + if response.status_code != 200: + logger.error(f"Failed to upload: {file}") + logger.error(response.text) + return None + + # Get the upload token + upload_token = response.text + logger.info(f"Upload token: {upload_token}") + + # Create the media item + logger.info("Creating new media item") + response = requests.post( + "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate", + headers={ + "Authorization": f"Bearer {oauth_token}", + "Content-type": "application/json", + }, + json={ + "newMediaItems": [ + { + "description": "", + "simpleMediaItem": { + "fileName": file.name, + "uploadToken": upload_token, + }, + } + ] + }, + ) + + # Check for errors + if response.status_code != 200: + logger.error(f"Failed to create media item: {file}") + logger.error(response.text) + return None + + # Log some info about the action + for new_item in response.json()["newMediaItemResults"]: + if "mediaItem" in new_item: + logger.info(f"Created media item: {new_item['mediaItem']['filename']}") + logger.info(f"URL: {new_item['mediaItem']['productUrl']}") + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="gp-upload", description="Upload a file to Google Photos" + ) + ap.add_argument("file", help="File to upload") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Authenticate + oauth_token = get_google_oauth_token() + if oauth_token is None: + return 1 + + # Upload + upload_file(Path(args.file), oauth_token) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From c445e44c507c8abe0b5e611e2ee2df7d256596a1 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 28 Nov 2023 15:17:58 -0500 Subject: [PATCH 275/326] Add a script that allows caddy to access a dir in selinux --- scripts/se-caddy-allow | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 scripts/se-caddy-allow diff --git a/scripts/se-caddy-allow b/scripts/se-caddy-allow new file mode 100644 index 0000000..95027eb --- /dev/null +++ b/scripts/se-caddy-allow @@ -0,0 +1,5 @@ +#! /bin/bash +set -ex + +sudo chcon -t httpd_sys_content_t $1 -R +sudo chcon -t httpd_sys_rw_content_t $1 -R From 8d34c609bc25d33a88d9894086ad47031e098b57 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 28 Nov 2023 15:18:06 -0500 Subject: [PATCH 276/326] fix perm --- scripts/se-caddy-allow | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/se-caddy-allow diff --git a/scripts/se-caddy-allow b/scripts/se-caddy-allow old mode 100644 new mode 100755 From ef84edee63474273548d90bd9eca1520e2feb505 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 28 Nov 2023 15:25:18 -0500 Subject: [PATCH 277/326] Add a DU macro --- configs/shells/bash/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 4a7d0df..6870c56 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -24,6 +24,7 @@ alias rdns="dig +short -x" alias ufw-status="sudo ufw status numbered" alias genuuid="python -c 'import uuid; print(uuid.uuid4())'" alias clipboard="xclip -selection clipboard" +alias filesize="du -hs" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From 64cfd3c38242c0d2693cf7148d3eebc8624d49c6 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 28 Nov 2023 15:56:30 -0500 Subject: [PATCH 278/326] helper for making symlinks --- scripts/ezlink | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ scripts/ezlink3 | 4 ++++ 2 files changed, 64 insertions(+) create mode 100755 scripts/ezlink create mode 100755 scripts/ezlink3 diff --git a/scripts/ezlink b/scripts/ezlink new file mode 100755 index 0000000..13ae9f6 --- /dev/null +++ b/scripts/ezlink @@ -0,0 +1,60 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import subprocess +from pathlib import Path + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog="ezlink", description="Easier symlink took") + ap.add_argument("pointer", help="Link that points to the destination", type=Path) + ap.add_argument("destination", help="Destination of the link", type=Path) + ap.add_argument( + "-f", "--force", help="Force the link to be created", action="store_true" + ) + ap.add_argument( + "--hard", help="Link directly to the destination inode", action="store_true" + ) + ap.add_argument("--absolute", "-a", help="Use absolute paths", action="store_true") + ap.add_argument( + "--dereference-destination", + help="Follow the destination if it is also a pointer", + action="store_true", + ) + ap.add_argument( + "--dry-run", help="Don't actually create the link", action="store_true" + ) + args = ap.parse_args() + + # Convert to absolute paths if requested + if args.absolute: + args.pointer = args.pointer.absolute() + args.destination = args.destination.absolute() + + # Construct the appropriate LN command + command = ["ln"] + if not args.dereference_destination: + command.append("-n") + if not args.hard: + command.append("-s") + if args.force: + command.append("-f") + command.append(str(args.destination)) + command.append(str(args.pointer)) + + # Print the command + print(" ".join(command)) + + # Run the command if not a dry run + if not args.dry_run: + return subprocess.run(command).returncode + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/ezlink3 b/scripts/ezlink3 new file mode 100755 index 0000000..627dea3 --- /dev/null +++ b/scripts/ezlink3 @@ -0,0 +1,4 @@ +#! /bin/bash +set -e + +python3 $(which ezlink) $@ \ No newline at end of file From 9bba4d0240c1e103b746f7b3ffb193e791cc5e46 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 29 Nov 2023 09:36:06 -0500 Subject: [PATCH 279/326] Rename script --- scripts/{se-caddy-allow => caddy-se-allow} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{se-caddy-allow => caddy-se-allow} (100%) diff --git a/scripts/se-caddy-allow b/scripts/caddy-se-allow similarity index 100% rename from scripts/se-caddy-allow rename to scripts/caddy-se-allow From db8fa77a4caea03f300ce1bf5aa99e682bb892b9 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 29 Nov 2023 14:55:41 -0500 Subject: [PATCH 280/326] Configure sheridan jumphosts --- configs/ssh/config | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/configs/ssh/config b/configs/ssh/config index 8bbea8b..45f2353 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -4,7 +4,7 @@ Host * !*.github.com !github.com IdentityFile %d/.ssh/id_ed25519_sk_rk_yk20572395 IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_rsa - VisualHostKey yes + # VisualHostKey yes # Github SSH adapter for restricted networks Host github.com gist.github.com @@ -57,6 +57,14 @@ Host 10.50.24.2 User admin # Sheridan College +Host db6.fast.sheridanc.on.ca + User user03 +Host dbr.fast.sheridanc.on.ca + User DataIntegrator +Host *.fast.sheridanc.on.ca + ProxyJump prattene@atlas.sheridanc.on.ca +Host atlas.sheridanc.on.ca + User prattene Host *.sheridanc.on.ca User prattene RequestTTY yes From 1331316f6ee7621c0b0ea432549d628b059b5246 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 29 Nov 2023 21:03:25 -0500 Subject: [PATCH 281/326] Update blink paths --- scripts/blink-check | 2 +- scripts/blink-fetch | 35 +++++++++++++++++++++++------------ scripts/blink-timelapse | 2 +- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/scripts/blink-check b/scripts/blink-check index af9eef4..d43188e 100755 --- a/scripts/blink-check +++ b/scripts/blink-check @@ -11,7 +11,7 @@ def main() -> int: # Handle program arguments ap = argparse.ArgumentParser(prog='blink-check', description='Check on a running blink-fetch cron task') ap.add_argument("hostname", help="[user@]hostname[:port] for SSH") - ap.add_argument("--image-dir", help="Remote directory containing fetched images", default="/tmp/blink") + ap.add_argument("--image-dir", help="Remote directory containing fetched images", default="/home/ewpratten/Pictures/blink") ap.add_argument("--camera-id", help="Camera ID", default="155295") ap.add_argument("--show-latest", "--show", "-s", help="Download and display the latest image (if possible)", action="store_true") ap.add_argument('-v', '--verbose', help='Enable verbose logging', action='store_true') diff --git a/scripts/blink-fetch b/scripts/blink-fetch index 31d9312..c98c163 100755 --- a/scripts/blink-fetch +++ b/scripts/blink-fetch @@ -14,11 +14,13 @@ from pathlib import Path logger = logging.getLogger(__name__) + def decdeg2dms(dd): mult = -1 if dd < 0 else 1 - mnt,sec = divmod(abs(dd)*3600, 60) - deg,mnt = divmod(mnt, 60) - return mult*deg, mult*mnt, mult*sec + mnt, sec = divmod(abs(dd) * 3600, 60) + deg, mnt = divmod(mnt, 60) + return mult * deg, mult * mnt, mult * sec + async def main() -> int: # Handle program arguments @@ -28,12 +30,18 @@ async def main() -> int: ap.add_argument("--username", help="Blink username", required=True) ap.add_argument("--password", help="Blink password") ap.add_argument("--camera-id", help="Camera ID", default="155295") - ap.add_argument("--output-dir", help="Output directory", default="/tmp/blink") - ap.add_argument("--no-2fa", help="Don't try to get 2FA credentials", action="store_true") + ap.add_argument("--output-dir", help="Output directory", default="~/Pictures/blink") + ap.add_argument( + "--no-2fa", help="Don't try to get 2FA credentials", action="store_true" + ) ap.add_argument("--no-exif", help="Don't write EXIF data", action="store_true") ap.add_argument("--exif-camera", help="Camera name", default="Blink Mini") - ap.add_argument("--exif-latitude", "--exif-lat", help="Camera latitude (Decimal Degrees)") - ap.add_argument("--exif-longitude", "--exif-lng", help="Camera longitude (Decimal Degrees)") + ap.add_argument( + "--exif-latitude", "--exif-lat", help="Camera latitude (Decimal Degrees)" + ) + ap.add_argument( + "--exif-longitude", "--exif-lng", help="Camera longitude (Decimal Degrees)" + ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) @@ -50,7 +58,9 @@ async def main() -> int: args.password = getpass.getpass(prompt="Blink Password: ") # Authenticate with Blink servers - auth = Auth({"username": args.username, "password": args.password}, no_prompt=args.no_2fa) + auth = Auth( + {"username": args.username, "password": args.password}, no_prompt=args.no_2fa + ) blink = Blink() blink.auth = auth await blink.start() @@ -72,8 +82,9 @@ async def main() -> int: # Create the output directory if it doesn't exist now = datetime.now() - out_file = Path( - f"{args.output_dir}/camera_{args.camera_id}.{now.strftime('%Y%m%d_%H%M%S')}.jpg" + out_file = ( + Path(args.output_dir).expanduser() + / f"camera_{args.camera_id}.{now.strftime('%Y%m%d_%H%M%S')}.jpg" ) out_file.parent.mkdir(parents=True, exist_ok=True) @@ -88,7 +99,7 @@ async def main() -> int: # Set the camera type image.model = args.exif_camera - + # If the user provided a latitude and longitude, set it # if args.exif_latitude and args.exif_longitude: # image.gps_latitude = decdeg2dms(float(args.exif_latitude)) @@ -98,7 +109,7 @@ async def main() -> int: # Set the timestamp image.datetime_original = now.strftime(exif.DATETIME_STR_FORMAT) - + # Write the EXIF data back to the file logger.info("Writing EXIF data") with open(out_file, "wb") as f: diff --git a/scripts/blink-timelapse b/scripts/blink-timelapse index a1e0c4a..0e202b2 100755 --- a/scripts/blink-timelapse +++ b/scripts/blink-timelapse @@ -16,7 +16,7 @@ def main() -> int: description="Generates timelapses from blink image captures", ) ap.add_argument("--camera-id", help="Camera ID", default="155295") - ap.add_argument("--image-dir", help="Image directory", default="/tmp/blink") + ap.add_argument("--image-dir", help="Image directory", default="~/Pictures/blink") ap.add_argument( "--output-dir", help="Output directory", default="~/Videos/BlinkTimelapse" ) From 496d011d63b8efacbac4bceaff975887dc7e91f1 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 29 Nov 2023 21:04:28 -0500 Subject: [PATCH 282/326] bugfix --- scripts/blink-timelapse | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/blink-timelapse b/scripts/blink-timelapse index 0e202b2..24f7c8b 100755 --- a/scripts/blink-timelapse +++ b/scripts/blink-timelapse @@ -36,7 +36,8 @@ def main() -> int: ) # Find all frames - frames = Path(args.image_dir).expanduser().glob(f"camera_{args.camera_id}.*.jpg") + image_dir = Path(args.image_dir).expanduser() + frames = image_dir.glob(f"camera_{args.camera_id}.*.jpg") frames = sorted(frames, key=lambda frame: frame.stat().st_mtime) logger.info(f"Found {len(frames)} frames") logger.info( @@ -61,7 +62,7 @@ def main() -> int: "-pattern_type", "glob", "-i", - f"{args.image_dir}/camera_{args.camera_id}.*.jpg", + f"{str(image_dir)}/camera_{args.camera_id}.*.jpg", "-c:v", "libx264", "-pix_fmt", From b1b6bf3dab69edba8491c51e079b94cacde57091 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 30 Nov 2023 11:58:58 -0500 Subject: [PATCH 283/326] Add image burn-in and clone --- scripts/blink-fetch | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/blink-fetch b/scripts/blink-fetch index c98c163..c0eaf79 100755 --- a/scripts/blink-fetch +++ b/scripts/blink-fetch @@ -11,6 +11,7 @@ from blinkpy.blinkpy import Blink from blinkpy.auth import Auth from blinkpy.helpers.util import json_load from pathlib import Path +from PIL import Image, ImageDraw logger = logging.getLogger(__name__) @@ -31,6 +32,9 @@ async def main() -> int: ap.add_argument("--password", help="Blink password") ap.add_argument("--camera-id", help="Camera ID", default="155295") ap.add_argument("--output-dir", help="Output directory", default="~/Pictures/blink") + ap.add_argument( + "--copy-latest", help="Copies the latest frame to this path", type=Path + ) ap.add_argument( "--no-2fa", help="Don't try to get 2FA credentials", action="store_true" ) @@ -90,6 +94,12 @@ async def main() -> int: logger.info(f"Writing image to: {out_file}") await camera.image_to_file(str(out_file)) + + # Draw the timestamp on the image in the bottom left corner + image = Image.open(out_file) + draw = ImageDraw.Draw(image) + draw.text((0, image.height - 10), now.strftime("%Y-%m-%d %H:%M:%S"), fill=(255, 255, 255), stroke_width=2, stroke_fill=(0, 0, 0)) + image.save(out_file) # Handle EXIF data if not args.no_exif: @@ -114,6 +124,12 @@ async def main() -> int: logger.info("Writing EXIF data") with open(out_file, "wb") as f: f.write(image.get_file()) + + # If we were asked to copy the latest frame, do so + if args.copy_latest: + logger.info(f"Copying latest frame to: {args.copy_latest}") + args.copy_latest.parent.mkdir(parents=True, exist_ok=True) + args.copy_latest.write_bytes(out_file.read_bytes()) return 0 From 63736c24724cd003e88764c4eb09ea600881b405 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 30 Nov 2023 15:22:59 -0500 Subject: [PATCH 284/326] Add a tool for listening to RBN data --- scripts/rbn-grep | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100755 scripts/rbn-grep diff --git a/scripts/rbn-grep b/scripts/rbn-grep new file mode 100755 index 0000000..e349db9 --- /dev/null +++ b/scripts/rbn-grep @@ -0,0 +1,88 @@ +#! /usr/bin/env python3 +import argparse +import sys +import re +import socket + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="rbn-grep", description="Grep against RBN data in real-time" + ) + ap.add_argument( + "--callsign", "-c", help="REGEX for the TX-ing callsign", default=".*" + ) + ap.add_argument( + "--spotter", "-s", help="REGEX for the spotting callsign", default=".*" + ) + ap.add_argument( + "--min-frequency", "--fl", help="Minimum frequency in kc", type=float, default=0 + ) + ap.add_argument( + "--max-frequency", + "--fh", + help="Maximum frequency in kc", + type=float, + default=sys.maxsize, + ) + ap.add_argument( + "--stream-type", + "--st", + help="Stream type", + default="analog", + choices=["analog", "digital"], + ) + ap.add_argument("--login-callsign", help="Login callsign", default="n0call") + args = ap.parse_args() + + # Compile regexes + callsign_regex = re.compile(args.callsign, re.IGNORECASE) + spotter_regex = re.compile(args.spotter, re.IGNORECASE) + + # Connect to the RBN Telnet servers + conn = socket.create_connection( + ("telnet.reversebeacon.net", 7000 if args.stream_type == "analog" else 7001) + ) + + # Log in + conn.send(f"{args.login_callsign}\n".encode("ascii")) + + # Read lines and filter + try: + while True: + # Read a line + lines = conn.recv(1024).decode("ascii").strip() + for line in lines.splitlines(): + line_split = [x for x in line.split(" ") if x] + + # Ignore bad lines + if not line.startswith("DX"): + continue + + # Parse the data + spotter = line_split[2] + frequency_kc = float(line_split[3]) + spotted = line_split[4] + + # Filter + if ( + not callsign_regex.match(spotted) + or not spotter_regex.match(spotter) + or frequency_kc < args.min_frequency + or frequency_kc > args.max_frequency + ): + continue + + # Print the line + print(line) + + except KeyboardInterrupt: + print("\nGoodbye") + conn.close() + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 9c6a10a210bfb08b13ae9c60a4692fe113cb139b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 30 Nov 2023 16:27:03 -0500 Subject: [PATCH 285/326] Add a script to control KX2 filters --- scripts/kxfilter | 139 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100755 scripts/kxfilter diff --git a/scripts/kxfilter b/scripts/kxfilter new file mode 100755 index 0000000..68ae056 --- /dev/null +++ b/scripts/kxfilter @@ -0,0 +1,139 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import serial + +logger = logging.getLogger(__name__) + + +def set_apf(s: serial.Serial, state: str) -> None: + if state == "on": + s.write(b"AP1;") + elif state == "off": + s.write(b"AP0;") + +def set_nb(s: serial.Serial, state: str) -> None: + if state == "on": + s.write(b"NB1;") + elif state == "off": + s.write(b"NB0;") + else: + s.write("NL{:0>2}00;".format(state).encode("ascii")) + s.write(b"NB1;") + +def set_preamp(s: serial.Serial, state: str) -> None: + if state == "on": + s.write(b"PA1;") + elif state == "off": + s.write(b"PA0;") + +def set_attenuator(s: serial.Serial, state: str) -> None: + if state == "on": + s.write(b"RA01;") + elif state == "off": + s.write(b"RA00;") + +def set_filter_bandwidth(s: serial.Serial, bandwidth: float) -> None: + s.write("BW{:0>4};".format(int(bandwidth * 100)).encode("ascii")) + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="kxfilter", description="Change filter settings on a KX2 or KX3" + ) + ap.add_argument( + "--audio-peaking-filter", + "--apf", + help="Control the Audio Peaking Filter", + choices=["on", "off"], + ) + ap.add_argument( + "--noise-blanker", + "--nb", + help="Control the noise blanker", + choices=["on", "off"] + [str(x) for x in range(0, 16)], + ) + ap.add_argument( + "--pre-amp", "--pa", help="Control the pre-amp", choices=["on", "off"] + ) + ap.add_argument( + "--attenuator", "--att", help="Control the attenuator", choices=["on", "off"] + ) + ap.add_argument( + "--filter-bandwidth", + "--bw", + help="Filter bandwidth", + type=float, + choices=[ + 0.05, + 0.10, + 0.15, + 0.20, + 0.25, + 0.30, + 0.35, + 0.40, + 0.45, + 0.5, + 0.6, + 0.7, + 0.8, + 0.9, + 1.0, + 1.2, + 1.4, + 1.6, + 2.0, + 2.4, + 2.8, + ], + ) + ap.add_argument("--device", "-d", help="Serial device", default="/dev/ttyUSB0") + ap.add_argument("--baud", "-b", help="Serial baud rate", default=38400, type=int) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + stream=sys.stderr, + ) + + # Connect to the radio + logger.debug(f"Connecting to radio: {args.device}") + serial_conn = serial.Serial(args.device, args.baud) + + # Handle APF + if args.audio_peaking_filter: + logger.info(f"Setting APF: {args.audio_peaking_filter}") + set_apf(serial_conn, args.audio_peaking_filter) + + # Handle NB + if args.noise_blanker: + logger.info(f"Setting Noise Blanker: {args.noise_blanker}") + set_nb(serial_conn, args.noise_blanker) + + # Handle PA + if args.pre_amp: + logger.info(f"Setting Pre-Amp: {args.pre_amp}") + set_preamp(serial_conn, args.pre_amp) + + # Handle RX ATT + if args.attenuator: + logger.info(f"Setting RX Attenuator: {args.attenuator}") + set_attenuator(serial_conn, args.attenuator) + + # Handle filter bandwidth + if args.filter_bandwidth: + logger.info(f"Setting Filter Bandwidth: {args.filter_bandwidth}") + set_filter_bandwidth(serial_conn, args.filter_bandwidth) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 08f3ae8b9911a8725146a02a771d7177d948dc14 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 30 Nov 2023 16:38:12 -0500 Subject: [PATCH 286/326] Add a tuning utility --- scripts/kxfilter | 23 ++++++++++------- scripts/kxtune | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 9 deletions(-) create mode 100755 scripts/kxtune diff --git a/scripts/kxfilter b/scripts/kxfilter index 68ae056..3546487 100755 --- a/scripts/kxfilter +++ b/scripts/kxfilter @@ -12,7 +12,8 @@ def set_apf(s: serial.Serial, state: str) -> None: s.write(b"AP1;") elif state == "off": s.write(b"AP0;") - + + def set_nb(s: serial.Serial, state: str) -> None: if state == "on": s.write(b"NB1;") @@ -21,22 +22,26 @@ def set_nb(s: serial.Serial, state: str) -> None: else: s.write("NL{:0>2}00;".format(state).encode("ascii")) s.write(b"NB1;") - + + def set_preamp(s: serial.Serial, state: str) -> None: if state == "on": s.write(b"PA1;") elif state == "off": s.write(b"PA0;") - + + def set_attenuator(s: serial.Serial, state: str) -> None: if state == "on": s.write(b"RA01;") elif state == "off": s.write(b"RA00;") - + + def set_filter_bandwidth(s: serial.Serial, bandwidth: float) -> None: s.write("BW{:0>4};".format(int(bandwidth * 100)).encode("ascii")) + def main() -> int: # Handle program arguments ap = argparse.ArgumentParser( @@ -106,27 +111,27 @@ def main() -> int: # Connect to the radio logger.debug(f"Connecting to radio: {args.device}") serial_conn = serial.Serial(args.device, args.baud) - + # Handle APF if args.audio_peaking_filter: logger.info(f"Setting APF: {args.audio_peaking_filter}") set_apf(serial_conn, args.audio_peaking_filter) - + # Handle NB if args.noise_blanker: logger.info(f"Setting Noise Blanker: {args.noise_blanker}") set_nb(serial_conn, args.noise_blanker) - + # Handle PA if args.pre_amp: logger.info(f"Setting Pre-Amp: {args.pre_amp}") set_preamp(serial_conn, args.pre_amp) - + # Handle RX ATT if args.attenuator: logger.info(f"Setting RX Attenuator: {args.attenuator}") set_attenuator(serial_conn, args.attenuator) - + # Handle filter bandwidth if args.filter_bandwidth: logger.info(f"Setting Filter Bandwidth: {args.filter_bandwidth}") diff --git a/scripts/kxtune b/scripts/kxtune new file mode 100755 index 0000000..b5ef0b1 --- /dev/null +++ b/scripts/kxtune @@ -0,0 +1,67 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import serial + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="kxtune", description="Tune a KX2 or KX3 to a new frequency" + ) + ap.add_argument("frequency", help="Frequency to tune to in KC", type=float) + ap.add_argument("--vfo", help="VFO to tune", choices=["a", "b"], default="a") + ap.add_argument( + "--mode", + help="Radio mode", + choices=["lsb", "usb", "cw", "fm", "am", "data", "cw-r", "data-r"], + ) + ap.add_argument("--device", "-d", help="Serial device", default="/dev/ttyUSB0") + ap.add_argument("--baud", "-b", help="Serial baud rate", default=38400, type=int) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Convert to Hz + frequency = int(args.frequency * 1000) + + # Connect to the radio + logger.debug(f"Connecting to radio: {args.device}") + serial_conn = serial.Serial(args.device, args.baud) + + # Send the tune command + cmd = f"F{args.vfo.upper()}{frequency:011d};" + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + # If we have a mode, set it + mode_id = { + "lsb": "1", + "usb": "2", + "cw": "3", + "fm": "4", + "am": "5", + "data": "6", + "cw-r": "7", + "data-r": "9", + }.get(args.mode) + if mode_id: + cmd = f"MD{mode_id};" + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 18f81a1ba63a7b2d88467bd96d6d4ce55150f5fa Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 30 Nov 2023 16:47:10 -0500 Subject: [PATCH 287/326] Add a utility for changing power output --- scripts/kxpwr | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 scripts/kxpwr diff --git a/scripts/kxpwr b/scripts/kxpwr new file mode 100755 index 0000000..47f536d --- /dev/null +++ b/scripts/kxpwr @@ -0,0 +1,51 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import serial + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="kxpwr", description="Set the TX power on a KX2" + ) + ap.add_argument("watts", help="Power level in watts", type=int) + ap.add_argument("--retune", help="Re-tunes the antenna after setting power", action="store_true") + ap.add_argument("--device", "-d", help="Serial device", default="/dev/ttyUSB0") + ap.add_argument("--baud", "-b", help="Serial baud rate", default=38400, type=int) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Connect to the radio + logger.debug(f"Connecting to radio: {args.device}") + serial_conn = serial.Serial(args.device, args.baud) + + # Set the power level + cmd = "PC{:0>3};".format(args.watts) + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + # Re-tune the antenna if needed + if args.retune: + cmd = "SWT20;" + logger.warning("Re-tuning antenna") + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From ac8f7cdc35ea7ac7db74ff97bdb5e29f3024ce70 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 30 Nov 2023 18:37:20 -0500 Subject: [PATCH 288/326] updates --- scripts/kxchat | 71 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/kxcq | 4 +++ scripts/kxlisten | 62 ++++++++++++++++++++++++++++++++++++++++ scripts/kxpoweroff | 42 +++++++++++++++++++++++++++ scripts/kxsend | 56 ++++++++++++++++++++++++++++++++++++ 5 files changed, 235 insertions(+) create mode 100755 scripts/kxchat create mode 100755 scripts/kxcq create mode 100755 scripts/kxlisten create mode 100755 scripts/kxpoweroff create mode 100755 scripts/kxsend diff --git a/scripts/kxchat b/scripts/kxchat new file mode 100755 index 0000000..7508af1 --- /dev/null +++ b/scripts/kxchat @@ -0,0 +1,71 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import serial +import subprocess + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="kxchat", description="Chat over CW using the keyboard" + ) + ap.add_argument("--tx-only", help="Only transmit, do not receive", action="store_true") + ap.add_argument("--device", "-d", help="Serial device", default="/dev/ttyUSB0") + ap.add_argument("--baud", "-b", help="Serial baud rate", default=38400, type=int) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + stream=sys.stderr, + ) + + # Spawn a kxlisten process and hook its STDOUT to our STDOUT + if not args.tx_only: + logger.debug(f"Starting kxlisten process") + kxlisten = subprocess.Popen( + ["kxlisten", "-d", args.device, "-b", str(args.baud)], + ) + + # Read lines from keyboard, and send them to the radio using kxsend + try: + while True: + # Read a line from the keyboard + line = sys.stdin.readline().strip() + + # If the line is empty, skip + if not line: + continue + + # Add a space onto the end of the line + line += " " + + # Send the line to the radio + logger.debug(f"Sending line: {line}") + kxsend = subprocess.Popen( + ["kxsend", "-d", args.device, "-b", str(args.baud), line], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + except KeyboardInterrupt: + logger.info("Done transmitting") + + # Stop the kxlisten process + if not args.tx_only: + logger.debug(f"Stopping kxlisten process") + kxlisten.terminate() + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/kxcq b/scripts/kxcq new file mode 100755 index 0000000..837599c --- /dev/null +++ b/scripts/kxcq @@ -0,0 +1,4 @@ +#! /bin/bash +set -ex + +kxsend "CQ CQ CQ DE VA3ZZA VA3ZZA CQ CQ K" -v diff --git a/scripts/kxlisten b/scripts/kxlisten new file mode 100755 index 0000000..a2b688e --- /dev/null +++ b/scripts/kxlisten @@ -0,0 +1,62 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import serial + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="kxlisten", description="Route inbound CW text to STDOUT" + ) + ap.add_argument("--stop", help="Stop listening", action="store_true") + ap.add_argument("--device", "-d", help="Serial device", default="/dev/ttyUSB0") + ap.add_argument("--baud", "-b", help="Serial baud rate", default=38400, type=int) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + stream=sys.stderr, + ) + + # Connect to the radio + logger.debug(f"Connecting to radio: {args.device}") + serial_conn = serial.Serial(args.device, args.baud) + + # Handle stopping + if args.stop: + cmd = "TT0;" + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + return 0 + + # Otherwise, start listening + cmd = "TT1;" + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + # Listen for text + try: + while True: + next_char = serial_conn.read().decode("ascii") + print(next_char, end="") + sys.stdout.flush() + except KeyboardInterrupt: + logger.info("Stopping") + cmd = "TT0;" + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/kxpoweroff b/scripts/kxpoweroff new file mode 100755 index 0000000..23dec14 --- /dev/null +++ b/scripts/kxpoweroff @@ -0,0 +1,42 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import serial + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="kxpoweroff", description="Turn off a KX2 or KX3" + ) + ap.add_argument("--device", "-d", help="Serial device", default="/dev/ttyUSB0") + ap.add_argument("--baud", "-b", help="Serial baud rate", default=38400, type=int) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Connect to the radio + logger.debug(f"Connecting to radio: {args.device}") + serial_conn = serial.Serial(args.device, args.baud) + + # Send the appropriate command + cmd = "PS0;" + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/kxsend b/scripts/kxsend new file mode 100755 index 0000000..a749a92 --- /dev/null +++ b/scripts/kxsend @@ -0,0 +1,56 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import serial + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="kxsend", description="Send a string over CW on a KX2" + ) + ap.add_argument("text", help="Text to send", nargs="+") + ap.add_argument("--speed", help="Transmit speed in WPM", type=int) + ap.add_argument("--device", "-d", help="Serial device", default="/dev/ttyUSB0") + ap.add_argument("--baud", "-b", help="Serial baud rate", default=38400, type=int) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + args.text = " ".join(args.text) + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Connect to the radio + logger.debug(f"Connecting to radio: {args.device}") + serial_conn = serial.Serial(args.device, args.baud) + + # If we have a specific speed, set it + if args.speed: + cmd = "KS{:0>3};".format(args.speed) + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + # Break the text into max 24 character chunks + chunks = [args.text[i:i+24] for i in range(0, len(args.text), 24)] + logger.info(f"Sending {len(chunks)} chunks") + + # Handle each chunk + for chunk in chunks: + # Send the text + cmd = f"KY {chunk};" + logger.debug(f"Sending command: {cmd}") + serial_conn.write(cmd.encode("ascii")) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 4f8c5ac4f3fdf80e831dd15babf51dfb2be2e8b0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 1 Dec 2023 20:14:02 -0500 Subject: [PATCH 289/326] Add a script for extracting GPU info from deadline --- scripts/deadline-gpu-inventory | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100755 scripts/deadline-gpu-inventory diff --git a/scripts/deadline-gpu-inventory b/scripts/deadline-gpu-inventory new file mode 100755 index 0000000..5246273 --- /dev/null +++ b/scripts/deadline-gpu-inventory @@ -0,0 +1,100 @@ +#! /usr/bin/env python +import argparse +import sys +import logging +import pyperclip +import re + +logger = logging.getLogger(__name__) + +GPU_FILTERS = [ + re.compile(r"(Intel\(R\)[a-zA-Z\d ]+)"), + re.compile(r"(NVIDIA [a-zA-Z\d ]+)"), +] + +MSRP_ESTIMATES = { + "NVIDIA RTX A5000": 5400, + "NVIDIA RTX A4000": 1600, + "NVIDIA Quadro M5000": 2000, + "NVIDIA Geforce RTX 2070": 800 +} + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog='deadline-gpu-inventory', description='Reads Deadline machine info from the clipboard and displays the GPU inventory') + ap.add_argument("--format", "-f", help="Output format", choices=["pretty", "tsv", "csv"], default="pretty") + ap.add_argument("--guess-cost", "-g", help="Guess the cost of the GPUs", action="store_true") + ap.add_argument('-v', '--verbose', help='Enable verbose logging', action='store_true') + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format='%(levelname)s: %(message)s', + ) + + # Read from clipboard + clipboard = pyperclip.paste() + + # Split clipboard into lines + lines = clipboard.splitlines() + + # Search for GPUs + gpus = [] + for line in lines: + for gpu_filter in GPU_FILTERS: + # Find any matches + match = gpu_filter.search(line) + if match: + # Add to list of GPUs + gpus.append(match.group(1)) + + # If we don't have any GPUs, exit + if not gpus: + logger.error("No GPUs found.") + logger.info("Are you sure you have copied the machine info to the clipboard?") + return 1 + + # Reshape the list into [(gpu, count)] + gpu_counts = {} + for gpu in gpus: + gpu_counts[gpu] = gpu_counts.get(gpu, 0) + 1 + max_count = max(gpu_counts.values()) + gpu_counts = list(gpu_counts.items()) + + # Sort the list by count + gpu_counts.sort(key=lambda x: x[1], reverse=True) + + if args.format == "pretty": + # Figure out the width of the largest count + count_width = len(str(max_count)) + + # Print the list + for gpu, count in gpu_counts: + print(f"{count:>{count_width}} {gpu}") + + elif args.format == "tsv": + # Print the list + for gpu, count in gpu_counts: + print(f"{count}\t{gpu}") + + elif args.format == "csv": + # Print the list + print("Count,GPU") + for gpu, count in gpu_counts: + print(f"{count},{gpu}") + + # If cost guessing is enabled, print the estimated cost + if args.guess_cost: + total_cost = 0 + known_cost_gpu_count = 0 + for gpu, count in gpu_counts: + if gpu in MSRP_ESTIMATES: + total_cost += MSRP_ESTIMATES[gpu] * count + known_cost_gpu_count += 1 + print(f"Estimated cost: ${total_cost}. ({known_cost_gpu_count} models included in estimate)") + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file From d96a04b9941729b413b9eb0e1c14dcefb26b0d2f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 1 Dec 2023 20:14:10 -0500 Subject: [PATCH 290/326] Add tmux config --- configs/tmux/.tmux.conf | 1 + install-linux.sh | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 configs/tmux/.tmux.conf diff --git a/configs/tmux/.tmux.conf b/configs/tmux/.tmux.conf new file mode 100644 index 0000000..c8a0605 --- /dev/null +++ b/configs/tmux/.tmux.conf @@ -0,0 +1 @@ +set -g mouse on \ No newline at end of file diff --git a/install-linux.sh b/install-linux.sh index 4e65d1e..f175a2e 100644 --- a/install-linux.sh +++ b/install-linux.sh @@ -122,6 +122,9 @@ fi # Memegen ln -nsf $EWCONFIG_ROOT/configs/memegen ~/.config/memegen +# Tmux +ln -sf $EWCONFIG_ROOT/configs/tmux/.tmux.conf ~/.tmux.conf + # -- Optional Configs -- set +x From 3f7fd81ed69ce48cb7af0406db5ef05e7bd6793e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 1 Dec 2023 20:14:28 -0500 Subject: [PATCH 291/326] Add a qrl macro --- scripts/kxqrl | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 scripts/kxqrl diff --git a/scripts/kxqrl b/scripts/kxqrl new file mode 100755 index 0000000..1a068f6 --- /dev/null +++ b/scripts/kxqrl @@ -0,0 +1,4 @@ +#! /bin/bash +set -ex + +kxsend "QRL?" -v From 5cb445da4919c44fea262df2872b44d6eae8ce91 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 10 Dec 2023 13:52:44 -0500 Subject: [PATCH 292/326] Add a script for manipulating filepaths in the clipboard --- scripts/clippath | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 scripts/clippath diff --git a/scripts/clippath b/scripts/clippath new file mode 100755 index 0000000..b170ae9 --- /dev/null +++ b/scripts/clippath @@ -0,0 +1,83 @@ +#! /usr/bin/env python +import pyperclip +import argparse +import sys +import logging +import pathlib +import platform + +logger = logging.getLogger(__name__) + + +def convert_to_unix(path: str, args: argparse.Namespace) -> str: + output = path + + # Switch the slashes to forward slashes + output = output.replace("\\", "/") + + # If the path starts with a drive letter, handle it + if len(output) >= 2 and output[1] == ":": + # Get the drive letter + drive_letter = output[0] + + # Strip the front of the path + output = output[2:] + + # Add the mount point + output = f"{args.drive_letter_mount}/{drive_letter}{output}" + + return output + + +def convert_to_windows(path: str, args: argparse.Namespace) -> str: + output = path + + # Flip the path separators + output = output.replace("/", "\\") + + return output + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="clippath", description="Manipulates file paths in the clipboard" + ) + ap.add_argument( + "--destination-format", "-d", help="Destination format", choices=["windows", "unix"], default="windows" + ) + ap.add_argument("--drive-letter-mount", "-m", help="Mount point for drive letters", default="/mnt") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Read from clipboard + clipboard = pyperclip.paste() + + # Convert to the desired format + if args.destination_format == "windows": + converted = convert_to_windows(clipboard, args) + elif args.destination_format == "unix": + converted = convert_to_unix(clipboard, args) + else: + logger.error("Invalid destination format") + return 1 + + # Put the new path back into the clipboard + converted = converted.replace("\n", "").strip().lstrip() + pyperclip.copy(converted) + logger.info("New path copied to clipboard") + logger.info(converted) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 4e481cc5e724f12c14bec495668bc0e6c39d9c80 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 10 Dec 2023 13:53:01 -0500 Subject: [PATCH 293/326] Allow windows screenshot shortcut to work in gnome --- configs/gnome/desktop-settings.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/gnome/desktop-settings.sh b/configs/gnome/desktop-settings.sh index 634ab70..c9b2de1 100644 --- a/configs/gnome/desktop-settings.sh +++ b/configs/gnome/desktop-settings.sh @@ -37,6 +37,9 @@ gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-2 "['2 gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-3 "['3']" # Switch to ws 3 gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['4']" # Switch to ws 4 +# Match the Windows screenshot behavior while also allowing the regular print screen key to work +gsettings set org.gnome.shell.keybindings show-screenshot-ui "['s', 'Print']" + # Generate custom keybinds if they do not yet exist keybindings=$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings) if [ "$keybindings" = "[]" ] || [ "$keybindings" = "@as []" ]; then From 928d51864fd284349d79838d16239e3ae2050986 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 14 Dec 2023 10:58:29 -0500 Subject: [PATCH 294/326] Add reload --- configs/shells/bash/macros.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 6870c56..3a981ec 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -165,7 +165,7 @@ wg-reload() { if [ $# != 1 ]; then echo "Usage: wg-reload " else - wg syncconf $1 <(wg-quick strip $1) + sudo wg syncconf $1 <(wg-quick strip $1) fi } From 7257d3378da08972d26d2729d41f92db167e6f1b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 14 Dec 2023 11:01:04 -0500 Subject: [PATCH 295/326] Double SUDO --- configs/shells/bash/macros.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 3a981ec..948ccc7 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -165,7 +165,7 @@ wg-reload() { if [ $# != 1 ]; then echo "Usage: wg-reload " else - sudo wg syncconf $1 <(wg-quick strip $1) + sudo wg syncconf $1 <(sudo wg-quick strip $1) fi } From e8dee828e60bf5e0da311fc88db7318a46f3536a Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 17 Dec 2023 15:56:40 -0500 Subject: [PATCH 296/326] Add a firewall preset for asterisk --- scripts/ufw-gen | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/scripts/ufw-gen b/scripts/ufw-gen index 5a120c7..efd18bf 100755 --- a/scripts/ufw-gen +++ b/scripts/ufw-gen @@ -19,10 +19,21 @@ PROFILES = { "comment": "Zola", "ports": [(1111, "tcp")], }, - "kdeconnect":{ - "comment":"KDE Connect", - "ports":[("1714:1764", "udp"), ("1714:1764", "tcp")] - } + "kdeconnect": { + "comment": "KDE Connect", + "ports": [("1714:1764", "udp"), ("1714:1764", "tcp")], + }, + "asterisk": { + "comment": "Asterisk", + "ports": [ + (5060, "udp"), + (4569, "udp"), + (4569, "tcp"), + (5060, "tcp"), + (5061, "tcp"), + ("10000:20000", "udp"), + ], + }, } From 7c2fe296962bb49b3a361a62f703dbaa12619ec5 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 20 Dec 2023 10:33:03 -0500 Subject: [PATCH 297/326] Add a macro to watch for arp replies --- configs/shells/bash/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 948ccc7..c03140b 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -25,6 +25,7 @@ alias ufw-status="sudo ufw status numbered" alias genuuid="python -c 'import uuid; print(uuid.uuid4())'" alias clipboard="xclip -selection clipboard" alias filesize="du -hs" +alias arp-watch="sudo tcpdump -nn -tt -q \"arp and arp[6:2] == 2\"" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From ee0180e618387dac359407f28bf57bb80cfe0f77 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 20 Dec 2023 14:46:35 -0500 Subject: [PATCH 298/326] ifpi v1 --- scripts/ifpi | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100755 scripts/ifpi diff --git a/scripts/ifpi b/scripts/ifpi new file mode 100755 index 0000000..8aa8d06 --- /dev/null +++ b/scripts/ifpi @@ -0,0 +1,163 @@ +#! /usr/bin/env python3 +import argparse +import sys +import os +import logging +import subprocess +import ipaddress +import re + +logger = logging.getLogger(__name__) + +HOSTNAME_CACHE = {} + +HOSTNAME_PATTERNS = { + "GitHub": [re.compile(r".*github\.com\.")], + "Google": [re.compile(r".*google\.com\."), re.compile(r".*1e100\.net\.")], + "Google Cloud": [re.compile(r".*googleusercontent\.com\.")], + "Amazon Web Services": [re.compile(r".*amazonaws\.com\.")], + "Cloudfront": [re.compile(r".*cloudfront\.net\.")], + "Evan's Infrastructure": [re.compile(r".*ewp\.fyi\.")], +} + + +def classify_traffic( + destination_addr: ipaddress.IPv4Address, destination_port: int, packet_proto: str +) -> str: + packet_proto = packet_proto.upper().replace(",", "") + + # Handle some easy cases + if destination_addr.is_multicast: + return "multicast" + if destination_port == 22 and packet_proto == "TCP": + return "SSH" + if destination_port == 53 and packet_proto == "UDP": + return "DNS" + + # Use nslookup to get the hostname + if destination_addr not in HOSTNAME_CACHE: + try: + hostname = ( + subprocess.check_output( + ["nslookup", str(destination_addr)], stderr=subprocess.DEVNULL + ) + .decode("utf-8") + .split("\n")[0] + .split(" ")[-1] + ) + HOSTNAME_CACHE[destination_addr] = hostname + except subprocess.CalledProcessError: + HOSTNAME_CACHE[destination_addr] = None + + # Get the hostname + hostname = HOSTNAME_CACHE[destination_addr] or destination_addr + + # If this is HTTP/HTTPS traffic, try to figure out the service + if (packet_proto == "TCP" and destination_port in [80, 443]) or ( + packet_proto == "UDP" and destination_port == 443 + ): + for service, patterns in HOSTNAME_PATTERNS.items(): + for pattern in patterns: + if pattern.match(str(hostname)): + return service + + # Fallbacks in case we can't figure anything else out + if packet_proto == "TCP" and destination_port == 443: + return f"HTTPS ({hostname})" + if packet_proto == "TCP" and destination_port == 80: + return f"HTTP ({hostname})" + if packet_proto == "TCP" and destination_port == 443: + return f"QUIC ({hostname})" + + return f"Unknown({packet_proto}, {destination_port}, {hostname})" + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog="ifpi", description="Interface Packet Inspector") + ap.add_argument("interface", help="Interface to listen on") + ap.add_argument( + "--local-subnet", + "-l", + help="Subnet(s) to consider local", + action="append", + ) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # If we are not root, re-launch ourselves with sudo + if not os.geteuid() == 0: + return subprocess.call(["sudo"] + sys.argv) + + # Convert the local subnets to IPNetwork objects + local_subnets = [] + if args.local_subnet: + for subnet in args.local_subnet: + local_subnets.append(ipaddress.ip_network(subnet)) + + # Launch tcpdump + tcpdump_args = [ + "tcpdump", + "-i", + args.interface, + "-nn", + "-tt", + "-q", + ] + process = subprocess.Popen( + tcpdump_args, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + ) + + # Read all lines as they are printed + for line in process.stdout: + line = line.decode("utf-8").strip() + + # The format is (time, proto, data) + timestamp, protocol, data = line.split(" ", 2) + + # We will only handle IP packets + if protocol not in ["IP", "IP6"]: + continue + + # Extract source and destination IPs, along with the metadata + routing, metadata = data.split(": ", 1) + source, destination = routing.split(" > ") + source_port, destination_port = ( + source.split(".")[-1], + destination.split(".")[-1], + ) + try: + source = ipaddress.ip_address(".".join(source.split(".")[:-1])) + destination = ipaddress.ip_address(".".join(destination.split(".")[:-1])) + except ValueError: + continue + + # Only pay attention to source addrs that are local + for subnet in local_subnets: + if source in subnet: + break + else: + continue + + # Classify the traffic + classification = classify_traffic( + destination, int(destination_port), metadata.lstrip().split(" ")[0] + ) + + print(f"{source}\t{classification}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 9dfadb8eaace4d06667c77b79712572e989354d9 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 20 Dec 2023 14:51:18 -0500 Subject: [PATCH 299/326] add ssh ignore option --- scripts/ifpi | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/ifpi b/scripts/ifpi index 8aa8d06..c9444d5 100755 --- a/scripts/ifpi +++ b/scripts/ifpi @@ -60,7 +60,7 @@ def classify_traffic( for pattern in patterns: if pattern.match(str(hostname)): return service - + # Fallbacks in case we can't figure anything else out if packet_proto == "TCP" and destination_port == 443: return f"HTTPS ({hostname})" @@ -82,6 +82,11 @@ def main() -> int: help="Subnet(s) to consider local", action="append", ) + ap.add_argument( + "--ignore-ssh", + help="Ignore SSH traffic", + action="store_true", + ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) @@ -153,6 +158,10 @@ def main() -> int: classification = classify_traffic( destination, int(destination_port), metadata.lstrip().split(" ")[0] ) + + # Handle ignoring SSH traffic + if args.ignore_ssh and classification == "SSH": + continue print(f"{source}\t{classification}") From 17812efff44f26571191360aba62efcead0d8766 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 31 Dec 2023 11:42:06 -0500 Subject: [PATCH 300/326] fix discord-less mode --- scripts/ableton-linux | 52 ++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/scripts/ableton-linux b/scripts/ableton-linux index 35cb45a..2feb4ea 100755 --- a/scripts/ableton-linux +++ b/scripts/ableton-linux @@ -101,16 +101,18 @@ def main() -> int: # Configure discord presence discord_presence = pypresence.Presence(DISCORD_CLIENT_ID) - discord_presence.connect() + if not args.no_presence: + discord_presence.connect() launch_start = int(time.time()) # Ensure we have wineasio if not (WINEASIO_SRC_PATH / "build64").exists(): - discord_presence.update( - start=launch_start, - large_image=DISCORD_ICON, - details="Compiling WineASIO...", - ) + if not args.no_presence: + discord_presence.update( + start=launch_start, + large_image=DISCORD_ICON, + details="Compiling WineASIO...", + ) build_wineasio() # Figure out the wineprefix @@ -120,11 +122,12 @@ def main() -> int: # Ensure that the bottle has the wineasio dll if not (wineprefix / ".wineasio-installed").is_file(): logger.info("Registering wineasio") - discord_presence.update( - start=launch_start, - large_image=DISCORD_ICON, - details="Registering WineASIO with Ableton...", - ) + if not args.no_presence: + discord_presence.update( + start=launch_start, + large_image=DISCORD_ICON, + details="Registering WineASIO with Ableton...", + ) subprocess.check_call( [WINEASIO_SRC_PATH / "wineasio-register"], env={"WINEPREFIX": str(wineprefix)}, @@ -156,18 +159,15 @@ def main() -> int: ) # Update the presence message - discord_presence.update( - start=launch_start, - large_image=DISCORD_ICON, - details="Working on a project", - buttons=[ - {"label": "Check out my music!", "url": "https://ewpratten.com/music"} - ], - ) - - # Immediately cancel the presence if requested - if args.no_presence: - discord_presence.close() + if not args.no_presence: + discord_presence.update( + start=launch_start, + large_image=DISCORD_ICON, + details="Working on a project", + buttons=[ + {"label": "Check out my music!", "url": "https://ewpratten.com/music"} + ], + ) # Launch Ableton via bottles if not args.dry_run: @@ -176,14 +176,16 @@ def main() -> int: ["bottles-cli", "run", "-b", args.bottle, "-p", args.program], env=ableton_env, ) - discord_presence.close() + if not args.no_presence: + discord_presence.close() return return_code else: logger.info("Dry run, not launching Ableton") logger.info("Press enter to continue") input() - discord_presence.close() + if not args.no_presence: + discord_presence.close() return 0 From f9376581131925e19a8552d1a30a5f9ce93fe5b9 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 31 Dec 2023 11:42:22 -0500 Subject: [PATCH 301/326] Add some common device macros --- configs/ssh/config | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/configs/ssh/config b/configs/ssh/config index 45f2353..1e05045 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -96,3 +96,17 @@ Host w6421 Host oci-arm HostName oci-arm.vpn.ewp.fyi User ubuntu + +# Pratten Machines +Host warren-desktop + HostName workstation.warren.vpn + +Host gianna-desktop + HostName workstation.gianna.vpn + +# Various Aliases +Host desktop + HostName desktop.evan.vpn.ewp.fyi + +Host laptop + HostName laptop.evan.vpn.ewp.fyi From 26ce50b99b32f7541dda92b7a686f3a93740d6b0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 31 Dec 2023 12:15:03 -0500 Subject: [PATCH 302/326] Add aspath macros --- configs/shells/bash/macros.sh | 70 ++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index c03140b..7819b63 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -66,8 +66,8 @@ fi # If we are running in a studio environment if [ ! -z "$EWP_IN_GURU_ENVIRONMENT" ]; then - alias guru_launcher3="python $GURU_PYTHON_ROOT/env/guru_launcher3.py" - alias cd-dev="cd /s/development/epratten" + alias guru_launcher3="python $GURU_PYTHON_ROOT/env/guru_launcher3.py" + alias cd-dev="cd /s/development/epratten" fi # Kill via pgrep @@ -75,7 +75,7 @@ nkill() { if [ $# != 1 ]; then echo "Usage: nkill " else - kill -9 $(pgrep $1) + kill -9 $(pgrep $1) fi } @@ -90,29 +90,29 @@ mkcd() { # Sources a .env source_env() { - env=${1:-.env} - [ ! -f "${env}" ] && { echo "Env file ${env} doesn't exist"; return 1; } - eval $(sed -e '/^\s*$/d' -e '/^\s*#/d' -e 's/=/="/' -e 's/$/"/' -e 's/^/export /' "${env}") + env=${1:-.env} + [ ! -f "${env}" ] && { echo "Env file ${env} doesn't exist"; return 1; } + eval $(sed -e '/^\s*$/d' -e '/^\s*#/d' -e 's/=/="/' -e 's/$/"/' -e 's/^/export /' "${env}") } # Auto-extract anything extract() { if [ -f $1 ]; then case $1 in - *.tar.bz2) tar xvjf $1 ;; - *.tar.gz) tar xvzf $1 ;; - *.bz2) bunzip2 $1 ;; - *.rar) unrar x $1 ;; - *.gz) gunzip $1 ;; - *.tar) tar xvf $1 ;; - *.tbz2) tar xvjf $1 ;; - *.tgz) tar xvzf $1 ;; - *.zip) unzip $1 ;; - *.Z) uncompress $1 ;; - *.7z) 7z x $1 ;; - *.tar.zst) tar --use-compress-program=unzstd -xvf $1 ;; - *.zst) zstd -d $1 ;; - *) echo "don't know how to extract '$1'..." ;; + *.tar.bz2) tar xvjf $1 ;; + *.tar.gz) tar xvzf $1 ;; + *.bz2) bunzip2 $1 ;; + *.rar) unrar x $1 ;; + *.gz) gunzip $1 ;; + *.tar) tar xvf $1 ;; + *.tbz2) tar xvjf $1 ;; + *.tgz) tar xvzf $1 ;; + *.zip) unzip $1 ;; + *.Z) uncompress $1 ;; + *.7z) 7z x $1 ;; + *.tar.zst) tar --use-compress-program=unzstd -xvf $1 ;; + *.zst) zstd -d $1 ;; + *) echo "don't know how to extract '$1'..." ;; esac else echo "'$1' is not a valid file!" @@ -126,7 +126,7 @@ genpass() { else echo $(openssl rand -base64 $1 | tr -d "\n") fi - + } # Sign a file with an SSH key @@ -177,7 +177,7 @@ wg-edit() { else sudo nvim /etc/wireguard/$1.conf fi -} +} # Print a wireguard config file wg-cat() { @@ -204,7 +204,7 @@ ewconfig-pull-zip(){ echo "You can't run this command when ~/.config/ewconfig is a git repo!" return 1 fi - + # Download the latest zip cd ~/Downloads curl -L https://ewp.fyi/config.zip -o ewconfig.zip @@ -212,7 +212,7 @@ ewconfig-pull-zip(){ unzip ewconfig.zip mv ewconfig-master ~/.config/ewconfig rm ewconfig.zip - + # Return to the original directory cd $cwd } @@ -232,7 +232,7 @@ ewconfig-reinstall() { echo "Usage: ewconfig-reinstall " return 1 fi - + # Execute through ewconfig-run ewconfig-run sh ./install-$1.sh } @@ -260,3 +260,23 @@ svg2png() { inkscape -z "$1.png" "$1" --export-type=png fi } + +# Get the AS Path to an IP +aspath() { + # There must be at least one argument (cab be more) + if [ $# -lt 1 ]; then + echo "Usage: aspath [args]" + else + mtr $@ -z -rw -c1 -G0.25 | tail -n +3 | awk '{print $2}' | grep -v AS\?\?\? | uniq | cut -c 3- | tr '\n' ',' | sed 's/,/ -> /g' | rev | cut -c 5- | rev + fi +} + +# Get the AS Path to an IP (include unknown hops) +aspath-long() { + # There must be at least one argument (cab be more) + if [ $# -lt 1 ]; then + echo "Usage: aspath-long [args]" + else + mtr $@ -z -rw -c1 -G0.25 | tail -n +3 | awk '{print $2}' | uniq | cut -c 3- | tr '\n' ',' | sed 's/,/ -> /g' | rev | cut -c 5- | rev + fi +} \ No newline at end of file From c7bab60cb3927aa771ba16b4e4584920f83ad8c8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 31 Dec 2023 12:15:11 -0500 Subject: [PATCH 303/326] Add a wake-on-lan script --- scripts/wol | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100755 scripts/wol diff --git a/scripts/wol b/scripts/wol new file mode 100755 index 0000000..5d32cf0 --- /dev/null +++ b/scripts/wol @@ -0,0 +1,57 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import socket +import struct + +logger = logging.getLogger(__name__) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog="wol", description="Wake On LAN") + ap.add_argument("mac", help="MAC address of the target machine") + ap.add_argument( + "-p", "--port", help="UDP port to send the magic packet to", type=int, default=9 + ) + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Parse MAC address + mac = args.mac.replace(":", "").replace("-", "").replace(".", "") + if len(mac) != 12: + logger.error("Invalid MAC address") + return 1 + mac = bytes.fromhex(mac) + + # Create magic packet + magic_packet = b"\xff" * 6 + mac * 16 + + # Try to broadcast magic packet over both IPv4 and IPv6 + try: + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + s.sendto(magic_packet, ("", args.port)) + except OSError as e: + logger.error("Failed to broadcast magic packet over IPv4: %s", e) + try: + with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s: + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + s.sendto(magic_packet, ("ff02::1", args.port)) + except OSError as e: + logger.error("Failed to broadcast magic packet over IPv6: %s", e) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From f5b2a19c334382c30d514ae75eb5ed40cc2f41f0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 3 Jan 2024 13:40:41 -0500 Subject: [PATCH 304/326] Force py3 --- scripts/ufw-del | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ufw-del b/scripts/ufw-del index f6dd513..11a5488 100755 --- a/scripts/ufw-del +++ b/scripts/ufw-del @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 import argparse import sys import logging @@ -47,4 +47,4 @@ def main() -> int: return 0 if __name__ == "__main__": - sys.exit(main()) \ No newline at end of file + sys.exit(main()) From 460f31f3074dd42373488f47186769aa1a666417 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 3 Jan 2024 21:23:20 -0500 Subject: [PATCH 305/326] handle no vpn --- scripts/guru-vpn | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/guru-vpn b/scripts/guru-vpn index fa5c189..9cffc38 100755 --- a/scripts/guru-vpn +++ b/scripts/guru-vpn @@ -61,7 +61,7 @@ def handle_connect(args: argparse.Namespace) -> int: return 1 # If we are connected to AS54041, we need to briefly kill the connection - if is_interface_up("vpn"): + if args.wireguard_support and is_interface_up("vpn"): print("Bringing down AS54041 VPN") subprocess.run(["sudo", "wg-quick", "down", "vpn"], check=True) @@ -95,7 +95,8 @@ def handle_connect(args: argparse.Namespace) -> int: # Bring AS54041 back up print("Bringing up AS54041 VPN") - subprocess.run(["sudo", "wg-quick", "up", "vpn"], check=True) + if args.wireguard_support: + subprocess.run(["sudo", "wg-quick", "up", "vpn"], check=True) def handle_disconnect(args: argparse.Namespace) -> int: @@ -115,6 +116,12 @@ def main() -> int: choices=["connect", "disconnect", "reconnect"], help="Operation to perform", ) + ap.add_argument( + "-w", + "--wireguard-support", + help="Handles wireguard interfaces", + action="store_true", + ) args = ap.parse_args() # Ensure we can actually get credentials from the Yubikey From 3c446f54484dff80ccb360dca5059cebaf931ec3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 7 Jan 2024 12:48:49 -0500 Subject: [PATCH 306/326] Add echolink to ufw gen --- scripts/ufw-gen | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ufw-gen b/scripts/ufw-gen index efd18bf..4cde602 100755 --- a/scripts/ufw-gen +++ b/scripts/ufw-gen @@ -34,6 +34,10 @@ PROFILES = { ("10000:20000", "udp"), ], }, + "elproxy": { + "comment": "ElProxy", + "ports": [(8100, "tcp"), (5198, "udp"), (5199, "udp"), (5200, "tcp")], + }, } From e00b5fafc3f7a097fedd915d0dc7e60b14b6fbec Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 7 Jan 2024 12:48:58 -0500 Subject: [PATCH 307/326] Add NBSP to TG4X --- keyboards/qmk/keymaps/tg4x/config.h | 5 ++++- keyboards/qmk/keymaps/tg4x/keymap.c | 2 +- keyboards/qmk/keymaps/tg4x/rules.mk | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/keyboards/qmk/keymaps/tg4x/config.h b/keyboards/qmk/keymaps/tg4x/config.h index f6abda1..1b8737d 100644 --- a/keyboards/qmk/keymaps/tg4x/config.h +++ b/keyboards/qmk/keymaps/tg4x/config.h @@ -1,4 +1,7 @@ #pragma once // Threshold for things considered a "tap" -#define TAPPING_TERM 300 \ No newline at end of file +#define TAPPING_TERM 300 + +// Use Linux unicode mode +#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX diff --git a/keyboards/qmk/keymaps/tg4x/keymap.c b/keyboards/qmk/keymaps/tg4x/keymap.c index 2d74274..cedf9af 100644 --- a/keyboards/qmk/keymaps/tg4x/keymap.c +++ b/keyboards/qmk/keymaps/tg4x/keymap.c @@ -40,7 +40,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { _____, KC_VOLD, KC_VOLU, KC_MUTE, _____, _____, _____, KC_PGUP, _____, KC_PGDN, KC_PSCR, KC_SCRL, KC_PAUS, KC_CAPS, KC_MPRV, KC_MPLY, KC_MNXT, _____, _____, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_INS, _____, _PASS, RGB_TOG, _____, _____, _____, KC_HOME, KC_END, _____, _____, _____, _PASS, _____, - _PASS, _PASS, _PASS, KC_SPACE, KC_SPACE, _____, _____, _____, _____ + _PASS, _PASS, _PASS, KC_SPACE, UC(0x00A0), _____, _____, _____, _____ ), }; diff --git a/keyboards/qmk/keymaps/tg4x/rules.mk b/keyboards/qmk/keymaps/tg4x/rules.mk index f37bec0..a7c99e9 100644 --- a/keyboards/qmk/keymaps/tg4x/rules.mk +++ b/keyboards/qmk/keymaps/tg4x/rules.mk @@ -3,3 +3,7 @@ BOOTLOADER = qmk-dfu # Enable bootloader keys BOOTMAGIC_ENABLE = yes + +# Enable Unicode +UNICODE_COMMON = yes +UNICODE_ENABLE = yes \ No newline at end of file From de09ba2413cbf87f0bf5d03cd68fd0d52d59eac8 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 7 Jan 2024 12:49:23 -0500 Subject: [PATCH 308/326] py3 --- scripts/ufw-gen | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ufw-gen b/scripts/ufw-gen index 4cde602..851470a 100755 --- a/scripts/ufw-gen +++ b/scripts/ufw-gen @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 import argparse import sys import logging From 7e4c7e8f9ea33f5091bffcd1c6aecb5e8ca61914 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 9 Jan 2024 11:56:29 -0500 Subject: [PATCH 309/326] fix path --- configs/nautilus/scripts/Open in Video Trimmer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/nautilus/scripts/Open in Video Trimmer b/configs/nautilus/scripts/Open in Video Trimmer index c6846c3..937a2f9 100755 --- a/configs/nautilus/scripts/Open in Video Trimmer +++ b/configs/nautilus/scripts/Open in Video Trimmer @@ -1,4 +1,4 @@ #! /bin/bash set -e -python3 ~/.config/ewconfig/configs/scripts/video_trimmer \ No newline at end of file +python3 ~/.config/ewconfig/scripts/video_trimmer \ No newline at end of file From ad05ea8c738c1645a8bb0b0aab7764d8a34ff084 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 12 Jan 2024 11:06:39 -0500 Subject: [PATCH 310/326] Add a script to get the IP of a client --- scripts/wg-get-client-ip | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100755 scripts/wg-get-client-ip diff --git a/scripts/wg-get-client-ip b/scripts/wg-get-client-ip new file mode 100755 index 0000000..d4a50b6 --- /dev/null +++ b/scripts/wg-get-client-ip @@ -0,0 +1,11 @@ +#! /bin/bash +set -e + +# We need 1 argument +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +# NOTE: The final `grep` call is needed to make this fail if the pubkey is not found +sudo wg show all dump | grep $1 | cut -f 4 | cut -d: -f1 | grep "" From 574552313aefa32134a43738e8aed7a3a104b87b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Fri, 12 Jan 2024 11:07:24 -0500 Subject: [PATCH 311/326] fix usage string --- scripts/wg-get-client-ip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wg-get-client-ip b/scripts/wg-get-client-ip index d4a50b6..c2f1450 100755 --- a/scripts/wg-get-client-ip +++ b/scripts/wg-get-client-ip @@ -3,7 +3,7 @@ set -e # We need 1 argument if [ $# -ne 1 ]; then - echo "Usage: $0 " + echo "Usage: wg-get-client-ip " exit 1 fi From 0f5824cdfc289aa1b205d4f89fa9ba7bcd401f4b Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 17 Jan 2024 15:29:55 -0500 Subject: [PATCH 312/326] Bring along ufw profiles --- .gitmodules | 3 +++ third_party/ufw-application-profiles | 1 + 2 files changed, 4 insertions(+) create mode 160000 third_party/ufw-application-profiles diff --git a/.gitmodules b/.gitmodules index 6558645..3c9089b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,3 +21,6 @@ [submodule "configs/nvim/third_party/usda-syntax"] path = configs/nvim/third_party/usda-syntax url = https://github.com/superfunc/usda-syntax +[submodule "third_party/ufw-application-profiles"] + path = third_party/ufw-application-profiles + url = https://github.com/ageis/ufw-application-profiles diff --git a/third_party/ufw-application-profiles b/third_party/ufw-application-profiles new file mode 160000 index 0000000..63cdef1 --- /dev/null +++ b/third_party/ufw-application-profiles @@ -0,0 +1 @@ +Subproject commit 63cdef13e1fcaa41da500763dc2ca95da0f31486 From 5f11316ebae5257d5d36df2197c1cc9dd3f07e2f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 17 Jan 2024 15:29:59 -0500 Subject: [PATCH 313/326] add snvim --- configs/shells/bash/macros.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index 7819b63..ed580d1 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -26,6 +26,7 @@ alias genuuid="python -c 'import uuid; print(uuid.uuid4())'" alias clipboard="xclip -selection clipboard" alias filesize="du -hs" alias arp-watch="sudo tcpdump -nn -tt -q \"arp and arp[6:2] == 2\"" +alias snvim="sudoedit" # WHOIS macros alias whois-afrinic="whois -h whois.afrinic.net" From ac657e9af64171154d00aeb8e33888885ea5a9d3 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Wed, 17 Jan 2024 20:57:16 -0500 Subject: [PATCH 314/326] shh windows --- configs/shells/bash/info.sh | 43 ++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/configs/shells/bash/info.sh b/configs/shells/bash/info.sh index b029333..dd42aed 100644 --- a/configs/shells/bash/info.sh +++ b/configs/shells/bash/info.sh @@ -1,38 +1,33 @@ # Define red and green based on the shell if [ -n "$BASH_VERSION" ]; then - red='\033[0;31m' - green='\033[0;32m' - reset_color='\033[0m' -elif [ -n "$ZSH_VERSION" ]; then - red="$fg[red]" - green="$fg[green]" + red='\033[0;31m' + green='\033[0;32m' + reset_color='\033[0m' + elif [ -n "$ZSH_VERSION" ]; then + red="$fg[red]" + green="$fg[green]" fi # Different OSes have different ways of displaying info if [ $(uname -s | grep -c BSD) -gt 0 ]; then # BSD - echo -e "${green}Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" - -elif [ $(uname -o | grep -c Msys) -gt 0 ]; then # Windows - echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" - + echo -e "${green}Platform:$reset_color $(uname -s) $(uname -r) $(uname -p)" + + elif [ $(uname -o | grep -c Msys) -gt 0 ]; then # Windows + echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" + else # Linux-y things - echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" - echo -e "${green}Uptime:$reset_color $(uptime -p)" + echo -e "${green}Platform:$reset_color $(uname -o) $(uname -r)" + echo -e "${green}Uptime:$reset_color $(uptime -p)" fi # Determine if $EWCONFIG_ROOT contains uncommitted changes +# Skip this if on Windows if [ -d $EWCONFIG_ROOT/.git ]; then - if [ -n "$(git -C $EWCONFIG_ROOT status --porcelain)" ]; then - echo -e "${red}ewconfig contains uncommitted changes$reset_color" - fi + if [ $(uname -o | grep -c Msys) -eq 0 ]; then + if [ -n "$(git -C $EWCONFIG_ROOT status --porcelain)" ]; then + echo -e "${red}ewconfig contains uncommitted changes$reset_color" + fi + fi fi -# # Determine if $EWCONFIG_ROOT is up-to-date with origin. Only do this if we have network connectivity. -# if [ -d $EWCONFIG_ROOT/.git ]; then -# if ping -c 1 -W 1 git.github.com &> /dev/null; then -# if [ -n "$(git -C $EWCONFIG_ROOT fetch --dry-run 2>&1 | grep -v 'up to date')" ]; then -# echo "$fg[yellow]ewconfig is not up-to-date with origin$reset_color" -# fi -# fi -# fi \ No newline at end of file From a6d73960b38b3346ddfd6ae3dd211946642f377c Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Sun, 21 Jan 2024 13:46:18 -0500 Subject: [PATCH 315/326] Use sudoedit for WG configs --- configs/shells/bash/macros.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/shells/bash/macros.sh b/configs/shells/bash/macros.sh index ed580d1..a030b2a 100644 --- a/configs/shells/bash/macros.sh +++ b/configs/shells/bash/macros.sh @@ -176,7 +176,7 @@ wg-edit() { if [ $# != 1 ]; then echo "Usage: wg-edit " else - sudo nvim /etc/wireguard/$1.conf + sudoedit /etc/wireguard/$1.conf fi } @@ -280,4 +280,4 @@ aspath-long() { else mtr $@ -z -rw -c1 -G0.25 | tail -n +3 | awk '{print $2}' | uniq | cut -c 3- | tr '\n' ',' | sed 's/,/ -> /g' | rev | cut -c 5- | rev fi -} \ No newline at end of file +} From 8c5f08ce04f7c90abcee89fb31a8535d03a1814e Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 30 Jan 2024 15:03:42 -0500 Subject: [PATCH 316/326] Add submodules --- .gitmodules | 9 +++++++++ configs/nvim/pack/echasnovski/start/mini.trailspace | 1 + configs/nvim/pack/neovim/start/nvim-lspconfig | 1 + configs/nvim/pack/smolck/start/command-completion.nvim | 1 + 4 files changed, 12 insertions(+) create mode 160000 configs/nvim/pack/echasnovski/start/mini.trailspace create mode 160000 configs/nvim/pack/neovim/start/nvim-lspconfig create mode 160000 configs/nvim/pack/smolck/start/command-completion.nvim diff --git a/.gitmodules b/.gitmodules index 3c9089b..d6e33fc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -24,3 +24,12 @@ [submodule "third_party/ufw-application-profiles"] path = third_party/ufw-application-profiles url = https://github.com/ageis/ufw-application-profiles +[submodule "configs/nvim/pack/smolck/start/command-completion.nvim"] + path = configs/nvim/pack/smolck/start/command-completion.nvim + url = https://github.com/smolck/command-completion.nvim +[submodule "configs/nvim/pack/echasnovski/start/mini.trailspace"] + path = configs/nvim/pack/echasnovski/start/mini.trailspace + url = https://github.com/echasnovski/mini.trailspace +[submodule "configs/nvim/pack/neovim/start/nvim-lspconfig"] + path = configs/nvim/pack/neovim/start/nvim-lspconfig + url = https://github.com/neovim/nvim-lspconfig diff --git a/configs/nvim/pack/echasnovski/start/mini.trailspace b/configs/nvim/pack/echasnovski/start/mini.trailspace new file mode 160000 index 0000000..60d0eca --- /dev/null +++ b/configs/nvim/pack/echasnovski/start/mini.trailspace @@ -0,0 +1 @@ +Subproject commit 60d0eca6703b55285e33b0da00105cde50d188df diff --git a/configs/nvim/pack/neovim/start/nvim-lspconfig b/configs/nvim/pack/neovim/start/nvim-lspconfig new file mode 160000 index 0000000..8917d2c --- /dev/null +++ b/configs/nvim/pack/neovim/start/nvim-lspconfig @@ -0,0 +1 @@ +Subproject commit 8917d2c830e04bf944a699b8c41f097621283828 diff --git a/configs/nvim/pack/smolck/start/command-completion.nvim b/configs/nvim/pack/smolck/start/command-completion.nvim new file mode 160000 index 0000000..56c98f8 --- /dev/null +++ b/configs/nvim/pack/smolck/start/command-completion.nvim @@ -0,0 +1 @@ +Subproject commit 56c98f8d59a88ed96a80d43abca74a60ba31ea3a From 046fec6bad273aba98bfdbd5fa99f1814ccc959d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 30 Jan 2024 15:03:52 -0500 Subject: [PATCH 317/326] Tweak various things --- configs/helix/config.toml | 13 +++ .../Multiplayer_mc.ewpratten.com/config.txt | 15 ++++ .../dim%0/mw$default_1.txt | 7 ++ .../Multiplayer_mc.sdf.org/config.txt | 3 + configs/nvim/init.vim | 13 +++ configs/vim/.vimrc | 5 ++ keyboards/qmk/keymaps/ferris/keymap.c | 87 +++++++++++-------- keyboards/qmk/keymaps/tg4x/config.h | 19 ++++ keyboards/qmk/keymaps/tg4x/rules.mk | 5 +- scripts/qmk-helper | 2 +- 10 files changed, 132 insertions(+), 37 deletions(-) create mode 100644 configs/helix/config.toml create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt diff --git a/configs/helix/config.toml b/configs/helix/config.toml new file mode 100644 index 0000000..0f3ee7c --- /dev/null +++ b/configs/helix/config.toml @@ -0,0 +1,13 @@ +[editor] +mouse = true +middle-click-paste = true +line-number = "absolute" +auto-completion = true +auto-format = false + +[editor.cursor-shape] +normal = "block" +insert = "bar" +select = "block" + + diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt new file mode 100644 index 0000000..86e49c9 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt @@ -0,0 +1,15 @@ +//waypoints config options +usingMultiworldDetection:false +ignoreServerLevelId:false +defaultMultiworldId:mw0,0,0 +teleportationEnabled:true +usingDefaultTeleportCommand:true +sortType:NONE +sortReversed:false + +//other config options +ignoreHeightmaps:false + +//dimension types (DO NOT EDIT) +dimensionType:minecraft$the_nether:minecraft$the_nether +dimensionType:minecraft$overworld:minecraft$overworld diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt new file mode 100644 index 0000000..b0f95fd --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt @@ -0,0 +1,7 @@ +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:visibility_type:destination +# +waypoint:Sand:S:1152:66:-1542:3:false:0:gui.xaero_default:false:0:0:false +waypoint:Base:B:1138:82:-1028:4:false:0:gui.xaero_default:false:0:0:false +waypoint:Temp mountain base:T:678:80:-274:5:false:0:gui.xaero_default:false:0:0:false +waypoint:Spawn:S:0:64:0:10:false:0:gui.xaero_default:false:0:0:false diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt index bc89407..725713a 100644 --- a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt @@ -11,3 +11,6 @@ sortReversed:false //other config options ignoreHeightmaps:false + +//dimension types (DO NOT EDIT) +dimensionType:minecraft$overworld:minecraft$overworld diff --git a/configs/nvim/init.vim b/configs/nvim/init.vim index 8347f88..cab8e5d 100644 --- a/configs/nvim/init.vim +++ b/configs/nvim/init.vim @@ -30,6 +30,15 @@ endif " Enable Leap lua require('leap').add_default_mappings() +" Enable Helix-style command suggestions +"lua require('command-completion').setup() + +" Enable trailing space detection +lua require('mini.trailspace').setup() + +" Configure floating window colours +highlight Pmenu ctermbg=none ctermfg=white + " VSCode-style comment toggling nnoremap :Commentary vnoremap :Commentary @@ -42,3 +51,7 @@ function! MkdirAndWrite() exec 'w' endfunction command Wmk call MkdirAndWrite() + +" LSP Support +"lua require "lspconfig".rust_analyzer.setup {} +"lua vim.keymap.set('n', 'e', vim.diagnostic.open_float) diff --git a/configs/vim/.vimrc b/configs/vim/.vimrc index 73ea498..d411eae 100644 --- a/configs/vim/.vimrc +++ b/configs/vim/.vimrc @@ -46,6 +46,11 @@ set shortmess+=I cnoreabbrev help getcmdtype() == ":" && getcmdline() == 'help' ? 'tab help' : 'help' cnoreabbrev h getcmdtype() == ":" && getcmdline() == 'h' ? 'tab help' : 'h' +" Configure netrw +let g:netrw_liststyle = 3 +let g:netrw_banner = 0 +let g:netrw_browse_split = 3 + " Enable spell checking if !exists('g:vscode') set spell diff --git a/keyboards/qmk/keymaps/ferris/keymap.c b/keyboards/qmk/keymaps/ferris/keymap.c index 3db33d0..28768f6 100644 --- a/keyboards/qmk/keymaps/ferris/keymap.c +++ b/keyboards/qmk/keymaps/ferris/keymap.c @@ -5,11 +5,13 @@ // Layer definitions enum ferris_layers { + // _HOME, + // _QWERTY, _MODMAK, - _NUMERIC, - _UTILITY, - _MACROS, - _RAINBOW, + // _NUMERIC, + // _UTILITY, + // _MACROS, + // _RAINBOW, }; // Shorthands @@ -21,40 +23,55 @@ enum ferris_layers { // clang-format off const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + // [_HOME] = LAYOUT( + // KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_BSPC, + // KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, + // KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + // KC_LSFT, KC_LCTL, KC_SPACE, KC_NO + // ), + + // [_QWERTY] = LAYOUT( + // KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, + // KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, + // KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_NO, + // KC_LCTL, KC_SPACE, KC_SPACE, KC_LSFT + // ) + [_MODMAK] = LAYOUT( KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_BSPC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, - KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_M, KC_K, KC_COMM, KC_DOT, - KC_LSFT, MO(_MACROS), LT(_UTILITY, KC_SPACE), LT(_NUMERIC, KC_SPACE) + KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_M, KC_K, KC_COMM, KC_DOT, + KC_LSFT, KC_LCTL, KC_SPACE, KC_SPACE + // KC_LSFT, MO(_MACROS), LT(_UTILITY, KC_SPACE), LT(_NUMERIC, KC_SPACE) ), - [_NUMERIC] = LAYOUT( - KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, /**/ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, - KC_1, KC_2, KC_3, KC_4, KC_5, /**/ KC_6, KC_7, KC_8, KC_9, KC_0, - KC_LALT, KC_NO, KC_NO, KC_NO, TO(_MODMAK), /**/ KC_LGUI, KC_EQL, KC_MINS, KC_F11, KC_F12, - KC_LSFT, KC_LCTL, /**/ KC_NO, KC_NO - ), + // [_NUMERIC] = LAYOUT( + // KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, /**/ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, + // KC_1, KC_2, KC_3, KC_4, KC_5, /**/ KC_6, KC_7, KC_8, KC_9, KC_0, + // KC_LALT, KC_NO, KC_NO, KC_NO, TO(_MODMAK), /**/ KC_LGUI, KC_EQL, KC_MINS, KC_F11, KC_F12, + // KC_LSFT, KC_LCTL, /**/ KC_NO, KC_NO + // ), - [_UTILITY] = LAYOUT( - KC_Q, KC_VOLD, KC_VOLU, KC_NO, KC_PSCR, /**/ LD_TERM, KC_HOME, KC_PGUP, KC_PGDN, KC_DEL, - KC_MPRV, KC_MPLY, KC_MNXT, KC_NO, KC_TAB, /**/ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_END, - KC_NO, KC_NO, KC_NO, CC_FMT, CC_COMM, /**/ KC_QUOTE, KC_SLSH, KC_LBRC, KC_RBRC, KC_BSLS, - KC_LSFT, KC_LCTL, /**/ KC_NO, KC_LGUI - ), + // [_UTILITY] = LAYOUT( + // KC_Q, KC_VOLD, KC_VOLU, KC_NO, KC_PSCR, /**/ LD_TERM, KC_HOME, KC_PGUP, KC_PGDN, KC_DEL, + // KC_MPRV, KC_MPLY, KC_MNXT, KC_NO, KC_TAB, /**/ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_END, + // KC_NO, KC_NO, KC_NO, CC_FMT, CC_COMM, /**/ KC_QUOTE, KC_SLSH, KC_LBRC, KC_RBRC, KC_BSLS, + // KC_LSFT, KC_LCTL, /**/ KC_NO, KC_LGUI + // ), - [_MACROS] = LAYOUT( - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, TO(_RAINBOW), - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_NO, KC_NO, KC_NO, KC_NO - ), + // [_MACROS] = LAYOUT( + // KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, TO(_RAINBOW), + // KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + // KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + // KC_NO, KC_NO, KC_NO, KC_NO + // ), - [_RAINBOW] = LAYOUT( - KC_ESC, KC_Q, KC_W, KC_E, KC_5, TO(_MODMAK), KC_NO, KC_NO, KC_NO, KC_NO, - KC_LSFT, KC_A, KC_S, KC_D, KC_G, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_SPACE, KC_X, KC_NO, KC_NO - ) + // [_RAINBOW] = LAYOUT( + // KC_ESC, KC_Q, KC_W, KC_E, KC_5, TO(_MODMAK), KC_NO, KC_NO, KC_NO, KC_NO, + // KC_LSFT, KC_A, KC_S, KC_D, KC_G, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + // KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + // KC_SPACE, KC_X, KC_NO, KC_NO + // ) }; // clang-format on @@ -71,11 +88,11 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { switch (keycode) { // Space cadet needs to be much slower than my default - case SC_LSPO: - case SC_LCPO: - return 200; - case LT(_NUMERIC, KC_SPACE): - return 1000; + // case SC_LSPO: + // case SC_LCPO: + // return 200; + // case LT(_NUMERIC, KC_SPACE): + // return 1000; default: return TAPPING_TERM; } diff --git a/keyboards/qmk/keymaps/tg4x/config.h b/keyboards/qmk/keymaps/tg4x/config.h index 1b8737d..7540ffc 100644 --- a/keyboards/qmk/keymaps/tg4x/config.h +++ b/keyboards/qmk/keymaps/tg4x/config.h @@ -5,3 +5,22 @@ // Use Linux unicode mode #define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX + +// Custom USB HID info +// #undef VENDOR_ID +// #undef PRODUCT_ID +// #undef DEVICE_VER +// #undef MANUFACTURER +// #undef PRODUCT +// #define VENDOR_ID 0x6570 // "ep" +// #define PRODUCT_ID 0x0458 // 4 "X" +// #define DEVICE_VER 0x0021 +// #define MANUFACTURER ewpratten +// #define PRODUCT tg4x + +// Lighting settings +#define RGBLIGHT_DEFAULT_MODE RGBLIGHT_MODE_STATIC_LIGHT +#define RGBLIGHT_DEFAULT_HUE 0 +#define RGBLIGHT_DEFAULT_SAT 255 +#define RGBLIGHT_DEFAULT_VAL 255 +#define RGBLIGHT_DEFAULT_ON true diff --git a/keyboards/qmk/keymaps/tg4x/rules.mk b/keyboards/qmk/keymaps/tg4x/rules.mk index a7c99e9..08d85df 100644 --- a/keyboards/qmk/keymaps/tg4x/rules.mk +++ b/keyboards/qmk/keymaps/tg4x/rules.mk @@ -6,4 +6,7 @@ BOOTMAGIC_ENABLE = yes # Enable Unicode UNICODE_COMMON = yes -UNICODE_ENABLE = yes \ No newline at end of file +UNICODE_ENABLE = yes + +# Enable RGB lighting +RGBLIGHT_ENABLE = yes diff --git a/scripts/qmk-helper b/scripts/qmk-helper index ec3821d..a3b6a47 100755 --- a/scripts/qmk-helper +++ b/scripts/qmk-helper @@ -152,7 +152,7 @@ def main() -> int: build_keymap(args.keyboard) elif args.mode == "flash": # Make sure that the flash mode is valid - if args.keyboard == "ferris-sweep" and args.flash_mode not in ["dfu-split-left", "dfu-split-right"]: + if args.keyboard == "ferris/sweep" and args.flash_mode not in ["dfu-split-left", "dfu-split-right"]: logger.error( "Invalid flash mode. Must be one of: dfu-split-left, dfu-split-right" ) From dd8015cccf9ad04e936f00a892f59f096723db9f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 13 Feb 2024 10:05:03 -0500 Subject: [PATCH 318/326] Add some more scripts --- scripts/git-authors-recursive | 20 ++++++++++++++++++++ scripts/mc-log-cat | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100755 scripts/git-authors-recursive create mode 100755 scripts/mc-log-cat diff --git a/scripts/git-authors-recursive b/scripts/git-authors-recursive new file mode 100755 index 0000000..71494c8 --- /dev/null +++ b/scripts/git-authors-recursive @@ -0,0 +1,20 @@ +#! /bin/bash + +git submodule foreach git authors | grep -v "^Entering" | python3 -c ' + +import sys +lines = sys.stdin.read().splitlines() +stats = {} +for line in lines: + count, author = line.lstrip().split("\t") + if author not in stats: + stats[author] = 0 + stats[author] += int(count) + +stats = list(stats.items()) +stats.sort(key=lambda s: s[1], reverse=True) + +for author, count in stats: + print(f"{count}\t{author}") + +' diff --git a/scripts/mc-log-cat b/scripts/mc-log-cat new file mode 100755 index 0000000..288a2c9 --- /dev/null +++ b/scripts/mc-log-cat @@ -0,0 +1,34 @@ +#! /usr/bin/env python3 + +import sys +import argparse +import subprocess +from pathlib import Path + +def main() -> int: + ap = argparse.ArgumentParser(prog="mc-log-cat", description="Analyze a set of Minecraft logs") + ap.add_argument("logs_dir", help="Path to the logs directory", type=Path) + args = ap.parse_args() + + # Find all compressed (old) logs + compressed_logs = list(args.logs_dir.glob("*.log.gz")) + compressed_logs.sort() + + # Non-destructively read the contents of each archive + log_files = [] + for file in compressed_logs: + file_contents = subprocess.run(["gunzip", "-c", file.as_posix()], capture_output=True, text=True) + log_files.append(file_contents.stdout) + + # Read and append the most recent log + if args.logs_dir.joinpath("latest.log").exists(): + log_files.append(args.logs_dir.joinpath("latest.log").read_text()) + + # Print the logs + for log in log_files: + print(log) + + return 0 + +if __name__ == "__main__": + sys.exit(main()) From 3941a8d2acb1c79e6222634486c8824f0a25e6ed Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 19 Feb 2024 15:08:08 -0500 Subject: [PATCH 319/326] Add mc waypoints --- .../XaeroWaypoints/Multiplayer_[§§]/config.txt | 14 ++++++++++++++ .../Multiplayer_[§§]/dim%0/mw$default_1.txt | 3 +++ .../Multiplayer_mc.ewpratten.com/config.txt | 3 +-- .../dim%0/mw$default_1.txt | 8 ++++---- .../Multiplayer_mc.sdf.org/config.txt | 1 + .../Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt | 4 ++++ .../Multiplayer_mc.yarc.world/config.txt | 14 ++++++++++++++ 7 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/config.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/dim%0/mw$default_1.txt create mode 100644 configs/minecraft/XaeroWaypoints/Multiplayer_mc.yarc.world/config.txt diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/config.txt new file mode 100644 index 0000000..390744a --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/config.txt @@ -0,0 +1,14 @@ +//waypoints config options +usingMultiworldDetection:false +ignoreServerLevelId:false +defaultMultiworldId:mw-4,0,2 +teleportationEnabled:true +usingDefaultTeleportCommand:true +sortType:NONE +sortReversed:false + +//other config options +ignoreHeightmaps:false + +//dimension types (DO NOT EDIT) +dimensionType:minecraft$overworld:minecraft$overworld diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/dim%0/mw$default_1.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/dim%0/mw$default_1.txt new file mode 100644 index 0000000..fa0d9c8 --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_[§§]/dim%0/mw$default_1.txt @@ -0,0 +1,3 @@ +# +#waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:visibility_type:destination +# diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt index 86e49c9..64c2a5c 100644 --- a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/config.txt @@ -1,7 +1,7 @@ //waypoints config options usingMultiworldDetection:false ignoreServerLevelId:false -defaultMultiworldId:mw0,0,0 +defaultMultiworldId:mw-13,1,0 teleportationEnabled:true usingDefaultTeleportCommand:true sortType:NONE @@ -11,5 +11,4 @@ sortReversed:false ignoreHeightmaps:false //dimension types (DO NOT EDIT) -dimensionType:minecraft$the_nether:minecraft$the_nether dimensionType:minecraft$overworld:minecraft$overworld diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt index b0f95fd..b892127 100644 --- a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.ewpratten.com/dim%0/mw$default_1.txt @@ -1,7 +1,7 @@ # #waypoint:name:initials:x:y:z:color:disabled:type:set:rotate_on_tp:tp_yaw:visibility_type:destination # -waypoint:Sand:S:1152:66:-1542:3:false:0:gui.xaero_default:false:0:0:false -waypoint:Base:B:1138:82:-1028:4:false:0:gui.xaero_default:false:0:0:false -waypoint:Temp mountain base:T:678:80:-274:5:false:0:gui.xaero_default:false:0:0:false -waypoint:Spawn:S:0:64:0:10:false:0:gui.xaero_default:false:0:0:false +waypoint:horse parking:H:970:68:2059:6:false:0:gui.xaero_default:false:0:0:false +waypoint:Home:H:-1647:98:-339:2:false:0:gui.xaero_default:false:0:0:false +waypoint:Village:V:-1575:64:-409:5:false:0:gui.xaero_default:false:0:0:false +waypoint:Spawn:S:-762:77:77:0:false:0:gui.xaero_default:false:0:0:false diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt index 725713a..9ee7aa3 100644 --- a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/config.txt @@ -14,3 +14,4 @@ ignoreHeightmaps:false //dimension types (DO NOT EDIT) dimensionType:minecraft$overworld:minecraft$overworld +dimensionType:minecraft$the_end:minecraft$the_end diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt index 662d898..03f7994 100644 --- a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.sdf.org/dim%0/mw$default_1.txt @@ -103,6 +103,10 @@ waypoint:[NDK] North Docks Station:S:-187:41:-1519:14:false:0:Subway Stations:fa waypoint:[BOH] Boathouse Station:S:-187:42:-839:14:false:0:Subway Stations:false:0:0:false waypoint:[RST] Riverside Station:S:-189:42:-321:14:false:0:Subway Stations:false:0:0:false waypoint:Spawn Central Station:S:-213:42:-258:13:false:0:Subway Stations:false:0:0:false +waypoint:Slime Farm:S:4975:4:5854:1:false:0:gui.xaero_default:false:0:0:false +waypoint:Northern Village:N:37:74:-10056:8:false:0:gui.xaero_default:false:0:0:false +waypoint:Creeper Farm:C:5092:5:5481:9:false:0:gui.xaero_default:false:0:0:false +waypoint:Warp Room:W:-4328:7:-2168:14:false:0:gui.xaero_default:false:0:0:false waypoint:New Base:N:-532:73:-2308:4:false:0:gui.xaero_default:false:0:1:false waypoint:Percy Home:X:-131:66:-102:9:false:0:gui.xaero_default:false:0:1:false waypoint:End Portal:E:921:23:1221:5:false:0:gui.xaero_default:false:0:0:false diff --git a/configs/minecraft/XaeroWaypoints/Multiplayer_mc.yarc.world/config.txt b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.yarc.world/config.txt new file mode 100644 index 0000000..33028ea --- /dev/null +++ b/configs/minecraft/XaeroWaypoints/Multiplayer_mc.yarc.world/config.txt @@ -0,0 +1,14 @@ +//waypoints config options +usingMultiworldDetection:false +ignoreServerLevelId:false +defaultMultiworldId:mw0,1,0 +teleportationEnabled:true +usingDefaultTeleportCommand:true +sortType:NONE +sortReversed:false + +//other config options +ignoreHeightmaps:false + +//dimension types (DO NOT EDIT) +dimensionType:minecraft$overworld:minecraft$overworld From dd7d702010409dd8810872ce77f8983e3a6d682f Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Mon, 19 Feb 2024 15:08:27 -0500 Subject: [PATCH 320/326] tweak git and ssh --- configs/git/.gitconfig | 2 + configs/shells/zsh/.zshrc | 4 + configs/ssh/config | 3 + scripts/git-detect-fake-authors | 6 ++ scripts/git-log-sqlite | 182 ++++++++++++++++++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100755 scripts/git-detect-fake-authors create mode 100755 scripts/git-log-sqlite diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 57f4a36..37ce2f3 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -47,3 +47,5 @@ [credential "https://gist.github.com"] helper = helper = !/usr/bin/gh auth git-credential +[push] + autoSetupRemote = true diff --git a/configs/shells/zsh/.zshrc b/configs/shells/zsh/.zshrc index c81007e..eae7fec 100644 --- a/configs/shells/zsh/.zshrc +++ b/configs/shells/zsh/.zshrc @@ -52,3 +52,7 @@ export SDKMAN_DIR="$HOME/.sdkman" # Flutter [[ -s "$HOME/pkg/flutter/bin" ]] && export PATH="$HOME/pkg/flutter/bin:$PATH" + +# Rye +[[ -s "$HOME/.rye/env" ]] && source "$HOME/.rye/env" +. "$HOME/.cargo/env" diff --git a/configs/ssh/config b/configs/ssh/config index 1e05045..831b512 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -5,6 +5,7 @@ Host * !*.github.com !github.com IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_rsa # VisualHostKey yes + VerifyHostKeyDNS ask # Github SSH adapter for restricted networks Host github.com gist.github.com @@ -91,6 +92,8 @@ Host td-prod td-prod2 td-prod3 td-prod4 User guru Host w6421 User "guru-domain\\epratten" + #RequestTTY yes + # RemoteCommand "C:\Program Files\Git\bin\bash.exe" --login # Personal Infra Host oci-arm diff --git a/scripts/git-detect-fake-authors b/scripts/git-detect-fake-authors new file mode 100755 index 0000000..5db63e8 --- /dev/null +++ b/scripts/git-detect-fake-authors @@ -0,0 +1,6 @@ +#! /bin/bash +# This script finds every time someone makes a commit under someone else's name +# NOTE: This includes co-authoring +set -e + +git-log-sqlite -q 'SELECT committer as Real, author as Fake, count(*) as Count FROM commits WHERE author NOT LIKE committer GROUP BY author, committer ORDER BY count DESC;' \ No newline at end of file diff --git a/scripts/git-log-sqlite b/scripts/git-log-sqlite new file mode 100755 index 0000000..d10782f --- /dev/null +++ b/scripts/git-log-sqlite @@ -0,0 +1,182 @@ +#! /usr/bin/env python3 +import subprocess +import sqlite3 +import argparse +import sys +import logging +from pathlib import Path +from typing import Dict + +logger = logging.getLogger(__name__) + +FIELDS = { + "ct": "timestamp", + "aN": "author", + "aE": "email", + "cN": "committer", + "cE": "committer_email", + "s": "subject", + "b": "body", + "N": "notes", +} + + +def read_properties() -> Dict[str, Dict[str, str]]: + output = {} + for field in FIELDS: + # Construct the log request + format_str = f"%H %{field}%x00" + + # Get the results + repo_results = subprocess.run( + ["git", "log", f"--format=format:{format_str}"], + capture_output=True, + text=True, + ).stdout + submodule_results = subprocess.run( + [ + "git", + "submodule", + "foreach", + "git", + "log", + f"--format=format:{format_str}", + ], + capture_output=True, + text=True, + ).stdout + + # Parse the results + all_results = repo_results + submodule_results + all_results = all_results.split("\x00") + for result in all_results: + if " " not in result or result == "": + continue + commit_hash, value = result.split(" ", 1) + if commit_hash.startswith("Entering"): + continue + if commit_hash.startswith("\n"): + commit_hash = commit_hash[1:] + if commit_hash not in output: + output[commit_hash] = {} + output[commit_hash][field] = value + + return output + + +def create_table(cursor: sqlite3.Cursor) -> None: + sql = "CREATE TABLE IF NOT EXISTS commits (hash TEXT PRIMARY KEY, " + for field in FIELDS.values(): + ty = "TEXT" + if field == "timestamp": + ty = "INTEGER" + if field == "hash": + ty = "TEXT PRIMARY KEY" + + sql += f"{field} {ty}, " + sql = sql[:-2] + ")" + logger.debug(f"Creating table with SQL: {sql}") + cursor.execute(sql) + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="git-log-sqlite", description="Interact with the git log using SQL" + ) + ap.add_argument( + "--dump", + help="Path to a sqlite3 database file to dump contents to. DELETES EXISTING FILE", + type=Path, + ) + ap.add_argument( + "--interactive", + "-i", + help="Start an interactive SQL session", + action="store_true", + ) + ap.add_argument("--query", "-q", help="Run a query and print the results") + ap.add_argument("--no-header", help="Do not print the header", action="store_true") + ap.add_argument("--mode", help="Set the mode for the sqlite3 command", default="table") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Interactive mode and query mode are mutually exclusive + if args.interactive and args.query: + logger.error("Interactive mode and query mode are mutually exclusive") + return 1 + + # If the user didn't specify anything, print the help message + if not (args.interactive or args.query): + ap.print_help() + return 1 + + # Read the properties + commits = read_properties() + logger.debug(f"Read {len(commits)} commits") + + # Open a connection to the database + if args.dump: + args.dump.parent.mkdir(parents=True, exist_ok=True) + args.dump.unlink(missing_ok=True) + conn = sqlite3.connect(args.dump if args.dump else ":memory:") + cursor = conn.cursor() + + # Create a table to store the data + create_table(cursor) + + # Insert the data into the table + rows = list(commits.items()) + rows.sort(key=lambda x: x[1]["ct"]) + for commit_hash, data in rows: + sql = "INSERT INTO commits VALUES (" + ",".join(["?"] * (len(FIELDS) + 1)) + ")" + values = [commit_hash] + [data.get(field, None) for field in FIELDS.keys()] + cursor.execute(sql, values) + + # Commit the changes + conn.commit() + + # If just dumping, we are done + if args.dump: + conn.close() + return 0 + + # Dump to a temp file + import tempfile + + temp_file = Path(tempfile.mkstemp()[1]) + temp_conn = sqlite3.connect(temp_file) + temp_conn.executescript("\n".join(conn.iterdump())) + temp_conn.commit() + conn.close() + + # Build the base sqlite command + sqlite_cmd = ["sqlite3", "--cmd", f".mode {args.mode}"] + if not args.no_header: + sqlite_cmd.append("--cmd") + sqlite_cmd.append(".headers on") + + # If running a query, do so + if args.query: + subprocess.run(sqlite_cmd + [temp_file, args.query]) + + # If running interactively, do so + if args.interactive: + subprocess.run(sqlite_cmd + ["--interactive", temp_file]) + + # Delete the temp file + temp_file.unlink() + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From e6ec60f11c45c6144d8eebbb36047da5166a011d Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 20 Feb 2024 14:53:02 -0500 Subject: [PATCH 321/326] Add a script that can monitor a pwnagotchi in a floating window --- scripts/pwnagotchi-watch | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100755 scripts/pwnagotchi-watch diff --git a/scripts/pwnagotchi-watch b/scripts/pwnagotchi-watch new file mode 100755 index 0000000..67ef62f --- /dev/null +++ b/scripts/pwnagotchi-watch @@ -0,0 +1,75 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import requests +import pygame +import time +import subprocess + +logger = logging.getLogger(__name__) + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog='pwnagotchi-watch', description='Watch the pwnagotchi screen remotely') + ap.add_argument("--host", help="Pwnagotchi hostname or IP address", default="10.0.0.2") + ap.add_argument("--port", help="Pwnagotchi port", type=int, default=8080) + ap.add_argument("-u", "--username", help="Pwnagotchi username", default="changeme") + ap.add_argument("-p", "--password", help="Pwnagotchi password", default="changeme") + ap.add_argument("--refresh-rate", help="Refresh rate in seconds", type=int, default=2) + ap.add_argument("--pin", help="Pin the window on top", action="store_true") + ap.add_argument('-v', '--verbose', help='Enable verbose logging', action='store_true') + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format='%(levelname)s: %(message)s', + ) + + # Create a window to draw the image to + pygame.init() + screen = pygame.display.set_mode((250,122)) + pygame.display.set_caption(f"pwnagotchi ({args.host})") + + # Pin the window on top + if args.pin: + logger.info("Pinning the window on top") + window_id = pygame.display.get_wm_info()["window"] + subprocess.run(["wmctrl", "-i", "-r", str(window_id), "-b", "add,above"], check=True) + + # Continuously fetch the pwnagotchi screen + while True: + try: + # Fetch the pwnagotchi screen + logger.debug(f"Fetching pwnagotchi screen from {args.host}:{args.port}") + response = requests.get(f"http://{args.host}:{args.port}/ui", auth=(args.username, args.password)) + response.raise_for_status() + screen_data = response.content + + # Draw the screen to the window + logger.debug("Drawing pwnagotchi screen") + with open("/tmp/pwnscreen.png", "wb") as f: + f.write(screen_data) + screen.fill((0,0,0)) + try: + img = pygame.image.load("/tmp/pwnscreen.png") + screen.blit(img, (0,0)) + pygame.display.flip() + except pygame.error as e: + logger.error(f"Failed to load pwnagotchi screen: {e}") + + except requests.RequestException as e: + logger.error(f"Failed to fetch pwnagotchi screen: {e}") + + time.sleep(args.refresh_rate) + + # If the window is closed, exit + for event in pygame.event.get(): + if event.type == pygame.QUIT: + return 0 + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file From 599c66f436bcf5d74860a10b611b0250498913d0 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 20 Feb 2024 14:53:24 -0500 Subject: [PATCH 322/326] Add an aprs passcode generator --- scripts/aprs-passcode | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100755 scripts/aprs-passcode diff --git a/scripts/aprs-passcode b/scripts/aprs-passcode new file mode 100755 index 0000000..a19f1dc --- /dev/null +++ b/scripts/aprs-passcode @@ -0,0 +1,28 @@ +#! /usr/bin/env python3 +import argparse +import sys + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="aprs-passcode", + description="Calculate the passcode used for APRS-IS authentication", + ) + ap.add_argument("callsign", help="APRS callsign") + args = ap.parse_args() + + # Perform passcode calculation + callsign = args.callsign.upper().split("-")[0] + code = 0x73E2 + for i, char in enumerate(callsign): + code ^= ord(char) << (8 if not i % 2 else 0) + passcode = code & 0x7FFF + + print(passcode) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From f70376816101e4417c1d7ce773c01c5568d0d108 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 20 Feb 2024 19:16:11 -0500 Subject: [PATCH 323/326] better error handling --- scripts/pwnagotchi-watch | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/scripts/pwnagotchi-watch b/scripts/pwnagotchi-watch index 67ef62f..2932e54 100755 --- a/scripts/pwnagotchi-watch +++ b/scripts/pwnagotchi-watch @@ -40,11 +40,24 @@ def main() -> int: # Continuously fetch the pwnagotchi screen while True: + + # If the window is closed, exit + for event in pygame.event.get(): + if event.type == pygame.QUIT: + return 0 + + # Attempt to fetch the pwnagotchi screen try: # Fetch the pwnagotchi screen logger.debug(f"Fetching pwnagotchi screen from {args.host}:{args.port}") - response = requests.get(f"http://{args.host}:{args.port}/ui", auth=(args.username, args.password)) - response.raise_for_status() + try: + response = requests.get(f"http://{args.host}:{args.port}/ui", auth=(args.username, args.password), timeout=1) + response.raise_for_status() + except Exception as e: + logger.error(f"Failed to connect to pwnagotchi at {args.host}:{args.port}") + logger.error(f"Error: {e}") + time.sleep(args.refresh_rate) + continue screen_data = response.content # Draw the screen to the window @@ -64,10 +77,6 @@ def main() -> int: time.sleep(args.refresh_rate) - # If the window is closed, exit - for event in pygame.event.get(): - if event.type == pygame.QUIT: - return 0 return 0 From 4b6a2501265a173827f487c203c7dc5e52ccb3c1 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Tue, 20 Feb 2024 19:16:17 -0500 Subject: [PATCH 324/326] Add sniffr config --- configs/ssh/config | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configs/ssh/config b/configs/ssh/config index 831b512..a03c938 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -5,7 +5,8 @@ Host * !*.github.com !github.com IdentityFile %d/.ssh/id_ed25519 IdentityFile %d/.ssh/id_rsa # VisualHostKey yes - VerifyHostKeyDNS ask + #VerifyHostKeyDNS ask + # Github SSH adapter for restricted networks Host github.com gist.github.com @@ -35,6 +36,9 @@ Host 10.80.0.218 PubkeyAcceptedKeyTypes +ssh-rsa HostKeyAlgorithms=+ssh-rsa +Host sniffr.home + User pi + # Default hostnames I may encounter in the wild Host openrepeater.local HostName openrepeater.local From 56e43e1e169db23ef461e3e953c11b3288d4c1ee Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 29 Feb 2024 11:24:09 -0500 Subject: [PATCH 325/326] Small cleanup --- .../3.x/scripts/addons/y_aligned_camera.py | 2 +- configs/git/.gitconfig | 1 + configs/ssh/config | 11 ++-- scripts/catto | 58 ------------------- 4 files changed, 6 insertions(+), 66 deletions(-) delete mode 100755 scripts/catto diff --git a/configs/blender/3.x/scripts/addons/y_aligned_camera.py b/configs/blender/3.x/scripts/addons/y_aligned_camera.py index 0216a4f..cb60c4e 100644 --- a/configs/blender/3.x/scripts/addons/y_aligned_camera.py +++ b/configs/blender/3.x/scripts/addons/y_aligned_camera.py @@ -1,6 +1,6 @@ bl_info = { "name": "Evan's Y-aligned Camera Creator", - "author": "Evan Pratten ", + "author": "Evan Pratten ", "version": (1, 0), "blender": (3, 0, 0), "description": "Adds a camera that is aligned with the Y axis by default", diff --git a/configs/git/.gitconfig b/configs/git/.gitconfig index 37ce2f3..2dc0487 100644 --- a/configs/git/.gitconfig +++ b/configs/git/.gitconfig @@ -47,5 +47,6 @@ [credential "https://gist.github.com"] helper = helper = !/usr/bin/gh auth git-credential + [push] autoSetupRemote = true diff --git a/configs/ssh/config b/configs/ssh/config index a03c938..606ad98 100644 --- a/configs/ssh/config +++ b/configs/ssh/config @@ -21,8 +21,8 @@ Host github.com gist.github.com Host unifi HostName dreammachinepro.local User root - #PreferredAuthentications password - # PubkeyAuthentication no + PreferredAuthentications password + PubkeyAuthentication no Host ewpratten-steamdeck HostName ewpratten-steamdeck.local @@ -36,9 +36,6 @@ Host 10.80.0.218 PubkeyAcceptedKeyTypes +ssh-rsa HostKeyAlgorithms=+ssh-rsa -Host sniffr.home - User pi - # Default hostnames I may encounter in the wild Host openrepeater.local HostName openrepeater.local @@ -113,7 +110,7 @@ Host gianna-desktop # Various Aliases Host desktop - HostName desktop.evan.vpn.ewp.fyi + HostName ewpratten-desktop.home Host laptop - HostName laptop.evan.vpn.ewp.fyi + HostName ewpratten-laptop.home diff --git a/scripts/catto b/scripts/catto deleted file mode 100755 index e7df79d..0000000 --- a/scripts/catto +++ /dev/null @@ -1,58 +0,0 @@ -#! /usr/bin/env python3 -import sys -import requests -import json -import argparse -import os -import tempfile -from pathlib import Path -import netrc - -def main() -> int: - ap = argparse.ArgumentParser() - ap.add_argument("image", help="Image to upload") - ap.add_argument("--no-compress", help="Don't compress the image", action="store_true") - args = ap.parse_args() - - # Load the API key from the .netrc file - if "catto.pictures" not in netrc.netrc().hosts: - print("No catto.pictures entry in .netrc file") - return 1 - login, account, password = netrc.netrc().authenticators("catto.pictures") - - # Parse the image to a path - image_path = Path(args.image) - - # Ensure the file actually exists - if not image_path.exists(): - print("File not found", file=sys.stderr) - return 1 - - # Compress the image to a temporary file - with tempfile.NamedTemporaryFile(suffix=image_path.suffix) as temp: - # Compress - if not args.no_compress: - os.system(f"convert {image_path} -quality 25% {temp.name}") - image_path = Path(temp.name) - - # Strip all exif data - os.system(f"exiftool -EXIF= {image_path}") - - # Upload the image - with open(image_path, "rb") as f: - r = requests.post( - "https://upload.catto.pictures", - files={"image": (temp.name, f, f"image/{image_path.suffix[1:]}")}, - headers={ - "Authorization": password, - "Domain": "img.ewpratten.com", - } - ) - if r.status_code != 200: - print(f"Error uploading image:\n{r.text}", file=sys.stderr) - return 1 - print(json.loads(r.text)["url"]) - -if __name__ == "__main__": - sys.exit(main()) - From 5302c416085306b47b9ed1e4e82d2112e1d780ec Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 29 Feb 2024 12:59:47 -0500 Subject: [PATCH 326/326] Add secret management script --- scripts/ewp-secrets | 182 +++++++++++++++++++++++++++++++++++++++++++ scripts/ewp-sendmail | 2 +- 2 files changed, 183 insertions(+), 1 deletion(-) create mode 100755 scripts/ewp-secrets diff --git a/scripts/ewp-secrets b/scripts/ewp-secrets new file mode 100755 index 0000000..3e2faa0 --- /dev/null +++ b/scripts/ewp-secrets @@ -0,0 +1,182 @@ +#! /usr/bin/env python3 +"""Evan's Secrets tool + +This aims to wrap the different secret management tools used on systems I work with. +For now, this only targets `secret-tool`, but I plan to add more in the future. +""" + +import argparse +import sys +import logging +import shutil +import subprocess +import sqlite3 +from pathlib import Path +from typing import Optional +from abc import ABC, abstractmethod + +logger = logging.getLogger(__name__) + +__all__ = ["EwpSecrets"] + + +class __SecretManager(ABC): + @abstractmethod + def runs_on_this_system(self) -> bool: ... + + @abstractmethod + def store(self, namespace: str, key: str, secret: str): ... + + @abstractmethod + def load(self, namespace: str, key: str) -> Optional[str]: ... + + +class GnomeKeyringSM(__SecretManager): + + def runs_on_this_system(self) -> bool: + return shutil.which("secret-tool") is not None + + def store(self, namespace: str, key: str, secret: str): + process = subprocess.Popen( + [ + "secret-tool", + "store", + "--label", + "Secret stored by ewp-secrets", + namespace, + key, + ], + stdin=subprocess.PIPE, + ) + process.communicate(input=secret.encode()) + process.wait() + + def load(self, namespace: str, key: str) -> Optional[str]: + try: + process = subprocess.run( + ["secret-tool", "lookup", namespace, key], + check=True, + capture_output=True, + ) + return process.stdout.decode() + except subprocess.CalledProcessError: + return None + + +class FilesystemSM(__SecretManager): + + def __init__( + self, + storage_path: Path = Path("~/.config/ewp-secrets/storage.sqlite3").expanduser(), + ): + # If the file doesn't exist, create it and restrict access + if not storage_path.exists(): + storage_path.parent.mkdir(parents=True, exist_ok=True) + storage_path.touch() + storage_path.chmod(0o600) + + self.conn = sqlite3.connect(storage_path) + self.conn.execute( + """CREATE TABLE IF NOT EXISTS secrets ( + namespace TEXT, + key TEXT, + secret TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + accessed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (namespace, key) + ) + """ + ) + + def runs_on_this_system(self) -> bool: + return True + + def store(self, namespace: str, key: str, secret: str): + self.conn.execute( + """INSERT INTO secrets (namespace, key, secret) + VALUES (?, ?, ?) + ON CONFLICT (namespace, key) DO UPDATE SET + (secret, updated_at) = (?, CURRENT_TIMESTAMP) + """, + (namespace, key, secret, secret), + ) + + def load(self, namespace: str, key: str) -> Optional[str]: + cursor = self.conn.execute( + """SELECT secret FROM secrets WHERE namespace = ? AND key = ?""", + (namespace, key), + ) + result = cursor.fetchone() + if result: + self.conn.execute( + """UPDATE secrets SET accessed_at = CURRENT_TIMESTAMP + WHERE namespace = ? AND key = ?""", + (namespace, key), + ) + return result[0] + return None + + +class EwpSecrets: + def __init__(self): + all_secret_managers = [GnomeKeyringSM(), FilesystemSM()] + self.secret_managers = [ + sm for sm in all_secret_managers if sm.runs_on_this_system() + ] + assert self.secret_managers, "No secret managers available on this system" + + def store(self, namespace: str, key: str, secret: str): + # Only write to the first (best) secret manager + self.secret_managers[0].store(namespace, key, secret) + + def load(self, namespace: str, key: str) -> Optional[str]: + # Try to read from each secret manager until we find the secret + for sm in self.secret_managers: + secret = sm.load(namespace, key) + if secret: + return secret + return None + + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser( + prog="ewp-secrets", description="Store and load secrets" + ) + ap.add_argument("action", help="Action to perform", choices=["store", "load"]) + ap.add_argument( + "-n", "--namespace", help="Namespace to store secrets in", required=True + ) + ap.add_argument("-k", "--key", help="Key to store secret under") + ap.add_argument( + "-v", "--verbose", help="Enable verbose logging", action="store_true" + ) + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format="%(levelname)s: %(message)s", + ) + + # Access the secret manager + secrets = EwpSecrets() + + # Perform the requested action + if args.action == "store": + secret = input("Enter the secret: ") + secrets.store(args.namespace, args.key, secret) + return 0 + elif args.action == "load": + secret = secrets.load(args.namespace, args.key) + if secret: + print(secret) + return 0 + else: + print("No secret found", file=sys.stderr) + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/ewp-sendmail b/scripts/ewp-sendmail index 8bdf55a..3dcdc13 100755 --- a/scripts/ewp-sendmail +++ b/scripts/ewp-sendmail @@ -27,7 +27,7 @@ def main() -> int: ) ap.add_argument( "--password", - help="Password to use for sending the email. Overrides the password in ~/.netrc", + help="Password to use for sending the email.", ) args = ap.parse_args()

  • Mf>(|=~cDbsrV{>ed^NoR9 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

    ysp}r#^}NUjh=m+z$e&yY6C7rJ_Qprs0Jj2F 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

    X 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