add bash-it

This commit is contained in:
2022-05-05 22:20:02 +02:00
parent 6a62a35d0d
commit 43701f0590
490 changed files with 33047 additions and 0 deletions

982
dot_bash_it/vendor/github.com/django/django/AUTHORS generated vendored Normal file
View File

@@ -0,0 +1,982 @@
Django was originally created in late 2003 at World Online, the Web division
of the Lawrence Journal-World newspaper in Lawrence, Kansas.
Here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS --
people who have submitted patches, reported bugs, added translations, helped
answer newbie questions, and generally made Django that much better:
Aaron Cannon <cannona@fireantproductions.com>
Aaron Swartz <http://www.aaronsw.com/>
Aaron T. Myers <atmyers@gmail.com>
Abeer Upadhyay <ab.esquarer@gmail.com>
Abhijeet Viswa <abhijeetviswa@gmail.com>
Abhinav Patil <https://github.com/ubadub/>
Abhishek Gautam <abhishekg1128@yahoo.com>
Adam Allred <adam.w.allred@gmail.com>
Adam Bogdał <adam@bogdal.pl>
Adam Donaghy
Adam Johnson <https://github.com/adamchainz>
Adam Malinowski <https://adammalinowski.co.uk/>
Adam Vandenberg
Adiyat Mubarak <adiyatmubarak@gmail.com>
Adnan Umer <u.adnan@outlook.com>
Adrian Holovaty <adrian@holovaty.com>
Adrien Lemaire <lemaire.adrien@gmail.com>
Afonso Fernández Nogueira <fonzzo.django@gmail.com>
AgarFu <heaven@croasanaso.sytes.net>
Ahmad Alhashemi <trans@ahmadh.com>
Ahmad Al-Ibrahim
Ahmed Eltawela <https://github.com/ahmedabt>
ajs <adi@sieker.info>
Akash Agrawal <akashrocksha@gmail.com>
Akis Kesoglou <akiskesoglou@gmail.com>
Aksel Ethem <aksel.ethem@gmail.com>
Akshesh Doshi <aksheshdoshi+django@gmail.com>
alang@bright-green.com
Alasdair Nicol <https://al.sdair.co.uk/>
Albert Wang <https://github.com/albertyw/>
Alcides Fonseca
Aldian Fazrihady <mobile@aldian.net>
Aleksandra Sendecka <asendecka@hauru.eu>
Aleksi Häkli <aleksi.hakli@iki.fi>
Alexander Dutton <dev@alexdutton.co.uk>
Alexander Myodov <alex@myodov.com>
Alexandr Tatarinov <tatarinov1997@gmail.com>
Alex Aktsipetrov <alex.akts@gmail.com>
Alex Becker <https://alexcbecker.net/>
Alex Couper <http://alexcouper.com/>
Alex Dedul
Alex Gaynor <alex.gaynor@gmail.com>
Alex Hill <alex@hill.net.au>
Alex Ogier <alex.ogier@gmail.com>
Alex Robbins <alexander.j.robbins@gmail.com>
Alexey Boriskin <alex@boriskin.me>
Alexey Tsivunin <most-208@yandex.ru>
Aljosa Mohorovic <aljosa.mohorovic@gmail.com>
Amit Chakradeo <https://amit.chakradeo.net/>
Amit Ramon <amit.ramon@gmail.com>
Amit Upadhyay <http://www.amitu.com/blog/>
A. Murat Eren <meren@pardus.org.tr>
Ana Belen Sarabia <belensarabia@gmail.com>
Ana Krivokapic <https://github.com/infraredgirl>
Andi Albrecht <albrecht.andi@gmail.com>
André Ericson <de.ericson@gmail.com>
Andrei Kulakov <andrei.avk@gmail.com>
Andreas
Andreas Mock <andreas.mock@web.de>
Andreas Pelme <andreas@pelme.se>
Andrés Torres Marroquín <andres.torres.marroquin@gmail.com>
Andrew Brehaut <https://brehaut.net/blog>
Andrew Clark <amclark7@gmail.com>
Andrew Durdin <adurdin@gmail.com>
Andrew Godwin <andrew@aeracode.org>
Andrew Pinkham <http://AndrewsForge.com>
Andrews Medina <andrewsmedina@gmail.com>
Andriy Sokolovskiy <me@asokolovskiy.com>
Andy Dustman <farcepest@gmail.com>
Andy Gayton <andy-django@thecablelounge.com>
andy@jadedplanet.net
Anssi Kääriäinen <akaariai@gmail.com>
ant9000@netwise.it
Anthony Briggs <anthony.briggs@gmail.com>
Anton Samarchyan <desecho@gmail.com>
Antoni Aloy
Antonio Cavedoni <http://cavedoni.com/>
Antonis Christofides <anthony@itia.ntua.gr>
Antti Haapala <antti@industrialwebandmagic.com>
Antti Kaihola <http://djangopeople.net/akaihola/>
Anubhav Joshi <anubhav9042@gmail.com>
Aram Dulyan
arien <regexbot@gmail.com>
Armin Ronacher
Aron Podrigal <aronp@guaranteedplus.com>
Artem Gnilov <boobsd@gmail.com>
Arthur <avandorp@gmail.com>
Arthur Koziel <http://arthurkoziel.com>
Arthur Rio <arthur.rio44@gmail.com>
Arvis Bickovskis <viestards.lists@gmail.com>
Aryeh Leib Taurog <http://www.aryehleib.com/>
A S Alam <aalam@users.sf.net>
Asif Saif Uddin <auvipy@gmail.com>
atlithorn <atlithorn@gmail.com>
Audrey Roy <http://audreymroy.com/>
av0000@mail.ru
Axel Haustant <noirbizarre@gmail.com>
Aymeric Augustin <aymeric.augustin@m4x.org>
Bahadır Kandemir <bahadir@pardus.org.tr>
Baishampayan Ghose
Baptiste Mispelon <bmispelon@gmail.com>
Barry Pederson <bp@barryp.org>
Bartolome Sanchez Salado <i42sasab@uco.es>
Bartosz Grabski <bartosz.grabski@gmail.com>
Bashar Al-Abdulhadi
Bastian Kleineidam <calvin@debian.org>
Batiste Bieler <batiste.bieler@gmail.com>
Batman
Batuhan Taskaya <batuhanosmantaskaya@gmail.com>
Baurzhan Ismagulov <ibr@radix50.net>
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
Ben Firshman <ben@firshman.co.uk>
Ben Godfrey <http://aftnn.org>
Benjamin Wohlwend <piquadrat@gmail.com>
Ben Khoo <khoobks@westnet.com.au>
Ben Slavin <benjamin.slavin@gmail.com>
Ben Sturmfels <ben@sturm.com.au>
Berker Peksag <berker.peksag@gmail.com>
Bernd Schlapsi
Bernhard Essl <me@bernhardessl.com>
berto
Bill Fenner <fenner@gmail.com>
Bjørn Stabell <bjorn@exoweb.net>
Bo Marchman <bo.marchman@gmail.com>
Bogdan Mateescu
Bojan Mihelac <bmihelac@mihelac.org>
Bouke Haarsma <bouke@haarsma.eu>
Božidar Benko <bbenko@gmail.com>
Brad Melin <melinbrad@gmail.com>
Brandon Chinn <https://brandonchinn178.github.io/>
Brant Harris
Brendan Hayward <brendanhayward85@gmail.com>
Brendan Quinn <brendan@cluefulmedia.com>
Brenton Simpson <http://theillustratedlife.com>
Brett Cannon <brett@python.org>
Brett Hoerner <bretthoerner@bretthoerner.com>
Brian Beck <http://blog.brianbeck.com/>
Brian Fabian Crain <http://www.bfc.do/>
Brian Harring <ferringb@gmail.com>
Brian Helba <brian.helba@kitware.com>
Brian Ray <http://brianray.chipy.org/>
Brian Rosner <brosner@gmail.com>
Bruce Kroeze <https://coderseye.com/>
Bruno Alla <alla.brunoo@gmail.com>
Bruno Renié <buburno@gmail.com>
brut.alll@gmail.com
Bryan Chow <bryan at verdjn dot com>
Bryan Veloso <bryan@revyver.com>
bthomas
btoll@bestweb.net
C8E
Caio Ariede <caio.ariede@gmail.com>
Calvin Spealman <ironfroggy@gmail.com>
Cameron Curry
Cameron Knight (ckknight)
Can Burak Çilingir <canburak@cs.bilgi.edu.tr>
Can Sarıgöl <ertugrulsarigol@gmail.com>
Carl Meyer <carl@oddbird.net>
Carles Pina i Estany <carles@pina.cat>
Carlos Eduardo de Paula <carlosedp@gmail.com>
Carlos Matías de la Torre <cmdelatorre@gmail.com>
Carlton Gibson <carlton.gibson@noumenal.es>
cedric@terramater.net
Chad Whitman <chad.whitman@icloud.com>
ChaosKCW
Charlie Leifer <coleifer@gmail.com>
charly.wilhelm@gmail.com
Chason Chaffin <chason@gmail.com>
Cheng Zhang
Chris Adams
Chris Beaven <smileychris@gmail.com>
Chris Bennett <chrisrbennett@yahoo.com>
Chris Cahoon <chris.cahoon@gmail.com>
Chris Chamberlin <dja@cdc.msbx.net>
Chris Jerdonek
Chris Jones <chris@brack3t.com>
Chris Lamb <chris@chris-lamb.co.uk>
Chris Streeter <chris@chrisstreeter.com>
Christian Barcenas <christian@cbarcenas.com>
Christian Metts
Christian Oudard <christian.oudard@gmail.com>
Christian Tanzer <tanzer@swing.co.at>
Christoffer Sjöbergsson
Christophe Pettus <xof@thebuild.com>
Christopher Adams <http://christopheradams.info>
Christopher Babiak <chrisbabiak@gmail.com>
Christopher Lenz <https://www.cmlenz.net/>
Christoph Mędrela <chris.medrela@gmail.com>
Chris Wagner <cw264701@ohio.edu>
Chris Wesseling <Chris.Wesseling@cwi.nl>
Chris Wilson <chris+github@qwirx.com>
Claude Paroz <claude@2xlibre.net>
Clint Ecker
colin@owlfish.com
Colin Wood <cwood06@gmail.com>
Collin Anderson <cmawebsite@gmail.com>
Collin Grady <collin@collingrady.com>
Colton Hicks <coltonbhicks@gmail.com>
Craig Blaszczyk <masterjakul@gmail.com>
crankycoder@gmail.com
Curtis Maloney (FunkyBob) <curtis@tinbrain.net>
dackze+django@gmail.com
Dagur Páll Ammendrup <dagurp@gmail.com>
Dane Springmeyer
Dan Fairs <dan@fezconsulting.com>
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
Daniel Duan <DaNmarner@gmail.com>
Daniele Procida <daniele@vurt.org>
Daniel Greenfeld
dAniel hAhler
Daniel Jilg <daniel@breakthesystem.org>
Daniel Lindsley <daniel@toastdriven.com>
Daniel Poelzleithner <https://poelzi.org/>
Daniel Pyrathon <pirosb3@gmail.com>
Daniel Roseman <http://roseman.org.uk/>
Daniel Tao <https://philosopherdeveloper.com/>
Daniel Wiesmann <daniel.wiesmann@gmail.com>
Danilo Bargen
Dan Johnson <danj.py@gmail.com>
Dan Palmer <dan@danpalmer.me>
Dan Poirier <poirier@pobox.com>
Dan Stephenson <http://dan.io/>
Dan Watson <http://danwatson.net/>
dave@thebarproject.com
David Ascher <https://ascher.ca/>
David Avsajanishvili <avsd05@gmail.com>
David Blewett <david@dawninglight.net>
David Brenneman <http://davidbrenneman.com>
David Cramer <dcramer@gmail.com>
David Danier <david.danier@team23.de>
David Eklund
David Foster <david@dafoster.net>
David Gouldin <dgouldin@gmail.com>
david@kazserve.org
David Krauth
David Larlet <https://larlet.fr/david/>
David Reynolds <david@reynoldsfamily.org.uk>
David Sanders <dsanders11@ucsbalum.com>
David Schein
David Tulig <david.tulig@gmail.com>
David Wobrock <david.wobrock@gmail.com>
Davide Ceretti <dav.ceretti@gmail.com>
Deep L. Sukhwani <deepsukhwani@gmail.com>
Deepak Thukral <deep.thukral@gmail.com>
Denis Kuzmichyov <kuzmichyov@gmail.com>
Dennis Schwertel <dennisschwertel@gmail.com>
Derek Willis <http://blog.thescoop.org/>
Deric Crago <deric.crago@gmail.com>
deric@monowerks.com
Deryck Hodge <http://www.devurandom.org/>
Dimitris Glezos <dimitris@glezos.com>
Dirk Datzert <dummy@habmalnefrage.de>
Dirk Eschler <dirk.eschler@gmx.net>
Dmitri Fedortchenko <zeraien@gmail.com>
Dmitry Jemerov <intelliyole@gmail.com>
dne@mayonnaise.net
Dolan Antenucci <antenucci.d@gmail.com>
Donald Harvey <donald@donaldharvey.co.uk>
Donald Stufft <donald@stufft.io>
Don Spaulding <donspauldingii@gmail.com>
Doug Beck <doug@douglasbeck.com>
Doug Napoleone <doug@dougma.com>
dready <wil@mojipage.com>
dusk@woofle.net
Dustyn Gibson <miigotu@gmail.com>
Ed Morley <https://github.com/edmorley>
eibaan@gmail.com
elky <http://elky.me/>
Emmanuelle Delescolle <https://github.com/nanuxbe>
Emil Stenström <em@kth.se>
enlight
Enrico <rico.bl@gmail.com>
Eric Boersma <eric.boersma@gmail.com>
Eric Brandwein <brandweineric@gmail.com>
Eric Floehr <eric@intellovations.com>
Eric Florenzano <floguy@gmail.com>
Eric Holscher <http://ericholscher.com>
Eric Moritz <http://eric.themoritzfamily.com/>
Eric Palakovich Carr <carreric@gmail.com>
Erik Karulf <erik@karulf.com>
Erik Romijn <django@solidlinks.nl>
eriks@win.tue.nl
Erwin Junge <erwin@junge.nl>
Esdras Beleza <linux@esdrasbeleza.com>
Espen Grindhaug <http://grindhaug.org/>
Eugene Lazutkin <http://lazutkin.com/blog/>
Evan Grim <https://github.com/egrim>
Fabrice Aneche <akh@nobugware.com>
Farhaan Bukhsh <farhaan.bukhsh@gmail.com>
favo@exoweb.net
fdr <drfarina@gmail.com>
Federico Capoano <nemesis@ninux.org>
Felipe Lee <felipe.lee.garcia@gmail.com>
Filip Noetzel <http://filip.noetzel.co.uk/>
Filip Wasilewski <filip.wasilewski@gmail.com>
Finn Gruwier Larsen <finn@gruwier.dk>
Flávio Juvenal da Silva Junior <flavio@vinta.com.br>
flavio.curella@gmail.com
Florian Apolloner <florian@apolloner.eu>
Florian Moussous <florian.moussous@gmail.com>
Fran Hrženjak <fran.hrzenjak@gmail.com>
Francisco Albarran Cristobal <pahko.xd@gmail.com>
Francisco Couzo <franciscouzo@gmail.com>
François Freitag <mail@franek.fr>
Frank Tegtmeyer <fte@fte.to>
Frank Wierzbicki
Frank Wiles <frank@revsys.com>
František Malina <fmalina@gmail.com>
Fraser Nevett <mail@nevett.org>
Gabriel Grant <g@briel.ca>
Gabriel Hurley <gabriel@strikeawe.com>
gandalf@owca.info
Garry Lawrence
Garry Polley <garrympolley@gmail.com>
Garth Kidd <http://www.deadlybloodyserious.com/>
Gary Wilson <gary.wilson@gmail.com>
Gasper Koren
Gasper Zejn <zejn@kiberpipa.org>
Gavin Wahl <gavinwahl@gmail.com>
Ge Hanbin <xiaomiba0904@gmail.com>
geber@datacollect.com
Geert Vanderkelen
George Karpenkov <george@metaworld.ru>
George Song <george@damacy.net>
George Vilches <gav@thataddress.com>
Georg "Hugo" Bauer <gb@hugo.westfalen.de>
Georgi Stanojevski <glisha@gmail.com>
Gerardo Orozco <gerardo.orozco.mosqueda@gmail.com>
Gil Gonçalves <lursty@gmail.com>
Girish Kumar <girishkumarkh@gmail.com>
Gisle Aas <gisle@aas.no>
Glenn Maynard <glenn@zewt.org>
glin@seznam.cz
GomoX <gomo@datafull.com>
Gonzalo Saavedra <gonzalosaavedra@gmail.com>
Gopal Narayanan <gopastro@gmail.com>
Graham Carlyle <graham.carlyle@maplecroft.net>
Grant Jenks <contact@grantjenks.com>
Greg Chapple <gregchapple1@gmail.com>
Gregor Allensworth <greg.allensworth@gmail.com>
Gregor Müllegger <gregor@muellegger.de>
Grigory Fateyev <greg@dial.com.ru>
Grzegorz Ślusarek <grzegorz.slusarek@gmail.com>
Guilherme Mesquita Gondim <semente@taurinus.org>
Guillaume Pannatier <guillaume.pannatier@gmail.com>
Gustavo Picon
hambaloney
Hang Park <hangpark@kaist.ac.kr>
Hannes Ljungberg <hannes.ljungberg@gmail.com>
Hannes Struß <x@hannesstruss.de>
Hasan Ramezani <hasan.r67@gmail.com>
Hawkeye
Helen Sherwood-Taylor <helen@rrdlabs.co.uk>
Henrique Romano <onaiort@gmail.com>
Henry Dang <henrydangprg@gmail.com>
Hidde Bultsma
Himanshu Chauhan <hchauhan1404@outlook.com>
hipertracker@gmail.com
Hiroki Kiyohara <hirokiky@gmail.com>
Honza Král <honza.kral@gmail.com>
Horst Gutmann <zerok@zerokspot.com>
Hugo Osvaldo Barrera <hugo@barrera.io>
HyukJin Jang <wkdgurwls00@naver.com>
Hyun Mi Ae
Iacopo Spalletti <i.spalletti@nephila.it>
Ian A Wilson <http://ianawilson.com>
Ian Clelland <clelland@gmail.com>
Ian G. Kelly <ian.g.kelly@gmail.com>
Ian Holsman <http://feh.holsman.net/>
Ian Lee <IanLee1521@gmail.com>
Ibon <ibonso@gmail.com>
Idan Gazit <idan@gazit.me>
Idan Melamed
Ifedapo Olarewaju <ifedapoolarewaju@gmail.com>
Igor Kolar <ike@email.si>
Illia Volochii <illia.volochii@gmail.com>
Ilya Semenov <semenov@inetss.com>
Ingo Klöcker <djangoproject@ingo-kloecker.de>
I.S. van Oostveen <v.oostveen@idca.nl>
ivan.chelubeev@gmail.com
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
Jaap Roes <jaap.roes@gmail.com>
Jack Moffitt <https://metajack.im/>
Jacob Burch <jacobburch@gmail.com>
Jacob Green
Jacob Kaplan-Moss <jacob@jacobian.org>
Jakub Paczkowski <jakub@paczkowski.eu>
Jakub Wilk <jwilk@jwilk.net>
Jakub Wiśniowski <restless.being@gmail.com>
james_027@yahoo.com
James Aylett
James Bennett <james@b-list.org>
James Murty
James Tauber <jtauber@jtauber.com>
James Timmins <jameshtimmins@gmail.com>
James Turk <dev@jamesturk.net>
James Wheare <django@sparemint.com>
Jannis Leidel <jannis@leidel.info>
Janos Guljas
Jan Pazdziora
Jan Rademaker
Jarek Głowacki <jarekwg@gmail.com>
Jarek Zgoda <jarek.zgoda@gmail.com>
Jason Davies (Esaj) <https://www.jasondavies.com/>
Jason Huggins <http://www.jrandolph.com/blog/>
Jason McBrayer <http://www.carcosa.net/jason/>
jason.sidabras@gmail.com
Jason Yan <tailofthesun@gmail.com>
Javier Mansilla <javimansilla@gmail.com>
Jay Parlar <parlar@gmail.com>
Jay Welborn <jesse.welborn@gmail.com>
Jay Wineinger <jay.wineinger@gmail.com>
J. Clifford Dyer <jcd@sdf.lonestar.org>
jcrasta@gmail.com
jdetaeye
Jeff Anderson <jefferya@programmerq.net>
Jeff Balogh <jbalogh@mozilla.com>
Jeff Hui <jeffkhui@gmail.com>
Jeffrey Gelens <jeffrey@gelens.org>
Jeff Triplett <jeff.triplett@gmail.com>
Jeffrey Yancey <jeffrey.yancey@gmail.com>
Jens Diemer <django@htfx.de>
Jens Page
Jensen Cochran <jensen.cochran@gmail.com>
Jeong-Min Lee <falsetru@gmail.com>
Jérémie Blaser <blaserje@gmail.com>
Jeremy Bowman <https://github.com/jmbowman>
Jeremy Carbaugh <jcarbaugh@gmail.com>
Jeremy Dunck <jdunck@gmail.com>
Jeremy Lainé <jeremy.laine@m4x.org>
Jesse Young <adunar@gmail.com>
Jezeniel Zapanta <jezeniel.zapanta@gmail.com>
jhenry <jhenry@theonion.com>
Jim Dalton <jim.dalton@gmail.com>
Jimmy Song <jaejoon@gmail.com>
Jiri Barton
Joachim Jablon <ewjoachim@gmail.com>
Joao Oliveira <joaoxsouls@gmail.com>
Joao Pedro Silva <j.pedro004@gmail.com>
Joe Heck <http://www.rhonabwy.com/wp/>
Joel Bohman <mail@jbohman.com>
Joel Heenan <joelh-django@planetjoel.com>
Joel Watts <joel@joelwatts.com>
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
Johan C. Stöver <johan@nilling.nl>
Johann Queuniet <johann.queuniet@adh.naellia.eu>
john@calixto.net
John D'Agostino <john.dagostino@gmail.com>
John D'Ambrosio <dambrosioj@gmail.com>
John Huddleston <huddlej@wwu.edu>
John Moses <moses.john.r@gmail.com>
John Paulett <john@paulett.org>
John Shaffer <jshaffer2112@gmail.com>
Jökull Sólberg Auðunsson <jokullsolberg@gmail.com>
Jon Dufresne <jon.dufresne@gmail.com>
Jonas Haag <jonas@lophus.org>
Jonatas C. D. <jonatas.cd@gmail.com>
Jonathan Buchanan <jonathan.buchanan@gmail.com>
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
Jonathan Feignberg <jdf@pobox.com>
Jonathan Slenders
Jordan Dimov <s3x3y1@gmail.com>
Jordi J. Tablada <jordi.joan@gmail.com>
Jorge Bastida <me@jorgebastida.com>
Jorge Gajon <gajon@gajon.org>
José Tomás Tocino García <josetomas.tocino@gmail.com>
Josef Rousek <josef.rousek@gmail.com>
Joseph Kocherhans <joseph@jkocherhans.com>
Josh Smeaton <josh.smeaton@gmail.com>
Joshua Cannon <joshdcannon@gmail.com>
Joshua Ginsberg <jag@flowtheory.net>
Jozko Skrablin <jozko.skrablin@gmail.com>
J. Pablo Fernandez <pupeno@pupeno.com>
jpellerin@gmail.com
Juan Catalano <catalanojuan@gmail.com>
Juan Manuel Caicedo <juan.manuel.caicedo@gmail.com>
Juan Pedro Fisanotti <fisadev@gmail.com>
Julia Elman
Julia Matsieva <julia.matsieva@gmail.com>
Julian Bez
Julien Phalip <jphalip@gmail.com>
Junyoung Choi <cupjoo@gmail.com>
junzhang.jn@gmail.com
Jure Cuhalev <gandalf@owca.info>
Justin Bronn <jbronn@gmail.com>
Justine Tunney <jtunney@gmail.com>
Justin Lilly <justinlilly@gmail.com>
Justin Michalicek <jmichalicek@gmail.com>
Justin Myles Holmes <justin@slashrootcafe.com>
Jyrki Pulliainen <jyrki.pulliainen@gmail.com>
Kadesarin Sanjek
Karderio <karderio@gmail.com>
Karen Tracey <kmtracey@gmail.com>
Karol Sikora <elektrrrus@gmail.com>
Katherine “Kati” Michel <kthrnmichel@gmail.com>
Kathryn Killebrew <kathryn.killebrew@gmail.com>
Katie Miller <katie@sub50.com>
Keith Bussell <kbussell@gmail.com>
Kenneth Love <kennethlove@gmail.com>
Kent Hauser <kent@khauser.net>
Kevin Grinberg <kevin@kevingrinberg.com>
Kevin Kubasik <kevin@kubasik.net>
Kevin McConnell <kevin.mcconnell@gmail.com>
Kieran Holland <http://www.kieranholland.com>
kilian <kilian.cavalotti@lip6.fr>
Kim Joon Hwan 김준환 <xncbf12@gmail.com>
Klaas van Schelven <klaas@vanschelven.com>
knox <christobzr@gmail.com>
konrad@gwu.edu
Kowito Charoenratchatabhan <kowito@felspar.com>
Krišjānis Vaiders <krisjanisvaiders@gmail.com>
krzysiek.pawlik@silvermedia.pl
Krzysztof Jurewicz <krzysztof.jurewicz@gmail.com>
Krzysztof Kulewski <kulewski@gmail.com>
kurtiss@meetro.com
Lakin Wecker <lakin@structuredabstraction.com>
Lars Yencken <lars.yencken@gmail.com>
Lau Bech Lauritzen
Laurent Luce <https://www.laurentluce.com/>
Laurent Rahuel <laurent.rahuel@gmail.com>
lcordier@point45.com
Leah Culver <leah.culver@gmail.com>
Leandra Finger <leandra.finger@gmail.com>
Lee Reilly <lee@leereilly.net>
Lee Sanghyuck <shlee322@elab.kr>
Leo "hylje" Honkanen <sealage@gmail.com>
Leo Shklovskii
Leo Soto <leo.soto@gmail.com>
lerouxb@gmail.com
Lex Berezhny <lex@damoti.com>
Liang Feng <hutuworm@gmail.com>
limodou
Lincoln Smith <lincoln.smith@anu.edu.au>
Liu Yijie <007gzs@gmail.com>
Loek van Gent <loek@barakken.nl>
Loïc Bistuer <loic.bistuer@sixmedia.com>
Lowe Thiderman <lowe.thiderman@gmail.com>
Luan Pablo <luanpab@gmail.com>
Lucas Connors <https://www.revolutiontech.ca/>
Luciano Ramalho
Ludvig Ericson <ludvig.ericson@gmail.com>
Luis C. Berrocal <luis.berrocal.1942@gmail.com>
Łukasz Langa <lukasz@langa.pl>
Łukasz Rekucki <lrekucki@gmail.com>
Luke Granger-Brown <django@lukegb.com>
Luke Plant <L.Plant.98@cantab.net>
Maciej Fijalkowski
Maciej Wiśniowski <pigletto@gmail.com>
Mads Jensen <https://github.com/atombrella>
Makoto Tsuyuki <mtsuyuki@gmail.com>
Malcolm Tredinnick
Manuel Saelices <msaelices@yaco.es>
Manuzhai
Marc Aymerich Gubern
Marc Egli <frog32@me.com>
Marcel Telka <marcel@telka.sk>
Marc Fargas <telenieko@telenieko.com>
Marc Garcia <marc.garcia@accopensys.com>
Marcin Wróbel
Marc Remolt <m.remolt@webmasters.de>
Marc Tamlyn <marc.tamlyn@gmail.com>
Marc-Aurèle Brothier <ma.brothier@gmail.com>
Marian Andre <django@andre.sk>
Marijn Vriens <marijn@metronomo.cl>
Mario Gonzalez <gonzalemario@gmail.com>
Mariusz Felisiak <felisiak.mariusz@gmail.com>
Mark Biggers <biggers@utsl.com>
Mark Gensler <mark.gensler@protonmail.com>
mark@junklight.com
Mark Lavin <markdlavin@gmail.com>
Mark Sandstrom <mark@deliciouslynerdy.com>
Markus Amalthea Magnuson <markus.magnuson@gmail.com>
Markus Holtermann <https://markusholtermann.eu>
Marten Kenbeek <marten.knbk+django@gmail.com>
Marti Raudsepp <marti@juffo.org>
martin.glueck@gmail.com
Martin Green
Martin Kosír <martin@martinkosir.net>
Martin Mahner <https://www.mahner.org/>
Martin Maney <http://www.chipy.org/Martin_Maney>
Martin von Gagern <gagern@google.com>
Mart Sõmermaa <http://mrts.pri.ee/>
Marty Alchin <gulopine@gamemusic.org>
Masashi Shibata <m.shibata1020@gmail.com>
masonsimon+django@gmail.com
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
Massimo Scamarcia <massimo.scamarcia@gmail.com>
Mathieu Agopian <mathieu.agopian@gmail.com>
Matías Bordese
Matt Boersma <matt@sprout.org>
Matt Croydon <http://www.postneo.com/>
Matt Deacalion Stevens <matt@dirtymonkey.co.uk>
Matt Dennenbaum
Matthew Flanagan <https://wadofstuff.blogspot.com/>
Matthew Schinckel <matt@schinckel.net>
Matthew Somerville <matthew-django@dracos.co.uk>
Matthew Tretter <m@tthewwithanm.com>
Matthew Wilkes <matt@matthewwilkes.name>
Matthias Kestenholz <mk@406.ch>
Matthias Pronk <django@masida.nl>
Matt Hoskins <skaffenuk@googlemail.com>
Matt McClanahan <https://mmcc.cx/>
Matt Riggott
Matt Robenolt <m@robenolt.com>
Mattia Larentis <mattia@laretis.eu>
Mattia Procopio <promat85@gmail.com>
Mattias Loverot <mattias@stubin.se>
mattycakes@gmail.com
Max Burstein <http://maxburstein.com>
Max Derkachev <mderk@yandex.ru>
Max Smolens <msmolens@gmail.com>
Maxime Lorant <maxime.lorant@gmail.com>
Maxime Turcotte <maxocub@riseup.net>
Maximilian Merz <django@mxmerz.de>
Maximillian Dornseif <md@hudora.de>
mccutchen@gmail.com
Meir Kriheli <http://mksoft.co.il/>
Michael S. Brown <michael@msbrown.net>
Michael Hall <mhall1@ualberta.ca>
Michael Josephson <http://www.sdjournal.com/>
Michael Manfre <mmanfre@gmail.com>
michael.mcewan@gmail.com
Michael Placentra II <someone@michaelplacentra2.net>
Michael Radziej <mir@noris.de>
Michael Sanders <m.r.sanders@gmail.com>
Michael Schwarz <michi.schwarz@gmail.com>
Michael Sinov <sihaelov@gmail.com>
Michael Thornhill <michael.thornhill@gmail.com>
Michal Chruszcz <troll@pld-linux.org>
michal@plovarna.cz
Michał Modzelewski <michal.modzelewski@gmail.com>
Mihai Damian <yang_damian@yahoo.com>
Mihai Preda <mihai_preda@yahoo.com>
Mikaël Barbero <mikael.barbero nospam at nospam free.fr>
Mike Axiak <axiak@mit.edu>
Mike Grouchy <https://mikegrouchy.com/>
Mike Malone <mjmalone@gmail.com>
Mike Richardson
Mike Wiacek <mjwiacek@google.com>
Mikhail Korobov <kmike84@googlemail.com>
Mikko Hellsing <mikko@sorl.net>
Mikołaj Siedlarek <mikolaj.siedlarek@gmail.com>
milkomeda
Milton Waddams
mitakummaa@gmail.com
mmarshall
Moayad Mardini <moayad.m@gmail.com>
Morgan Aubert <morgan.aubert@zoho.com>
Moritz Sichert <moritz.sichert@googlemail.com>
Morten Bagai <m@bagai.com>
msaelices <msaelices@gmail.com>
msundstr
Mushtaq Ali <mushtaak@gmail.com>
Mykola Zamkovoi <nickzam@gmail.com>
Nadège Michel <michel.nadege@gmail.com>
Nagy Károly <charlie@rendszergazda.com>
Nasimul Haque <nasim.haque@gmail.com>
Nasir Hussain <nasirhjafri@gmail.com>
Natalia Bidart <nataliabidart@gmail.com>
Nate Bragg <jonathan.bragg@alum.rpi.edu>
Nathan Gaberel <nathan@gnab.fr>
Neal Norwitz <nnorwitz@google.com>
Nebojša Dorđević
Ned Batchelder <https://nedbatchelder.com/>
Nena Kojadin <nena@kiberpipa.org>
Niall Dalton <niall.dalton12@gmail.com>
Niall Kelly <duke.sam.vimes@gmail.com>
Nick Efford <nick@efford.org>
Nick Lane <nick.lane.au@gmail.com>
Nick Pope <nick@nickpope.me.uk>
Nick Presta <nick@nickpresta.ca>
Nick Sandford <nick.sandford@gmail.com>
Nick Sarbicki <nick.a.sarbicki@gmail.com>
Niclas Olofsson <n@niclasolofsson.se>
Nicola Larosa <nico@teknico.net>
Nicolas Lara <nicolaslara@gmail.com>
Nicolas Noé <nicolas@niconoe.eu>
Niran Babalola <niran@niran.org>
Nis Jørgensen <nis@superlativ.dk>
Nowell Strite <https://nowell.strite.org/>
Nuno Mariz <nmariz@gmail.com>
oggie rob <oz.robharvey@gmail.com>
oggy <ognjen.maric@gmail.com>
Oliver Beattie <oliver@obeattie.com>
Oliver Rutherfurd <http://rutherfurd.net/>
Olivier Sels <olivier.sels@gmail.com>
Olivier Tabone <olivier.tabone@ripplemotion.fr>
Orestis Markou <orestis@orestis.gr>
Orne Brocaar <http://brocaar.com/>
Oscar Ramirez <tuxskar@gmail.com>
Ossama M. Khayat <okhayat@yahoo.com>
Owen Griffiths
Pablo Martín <goinnn@gmail.com>
Panos Laganakos <panos.laganakos@gmail.com>
Paolo Melchiorre <paolo@melchiorre.org>
Pascal Hartig <phartig@rdrei.net>
Pascal Varet
Patrik Sletmo <patrik.sletmo@gmail.com>
Paul Bissex <http://e-scribe.com/>
Paul Collier <paul@paul-collier.com>
Paul Collins <paul.collins.iii@gmail.com>
Paul Donohue <django@PaulSD.com>
Paul Lanier <planier@google.com>
Paul McLanahan <paul@mclanahan.net>
Paul McMillan <Paul@McMillan.ws>
Paulo Poiati <paulogpoiati@gmail.com>
Paulo Scardine <paulo@scardine.com.br>
Paul Smith <blinkylights23@gmail.com>
Pavel Kulikov <kulikovpavel@gmail.com>
pavithran s <pavithran.s@gmail.com>
Pavlo Kapyshin <i@93z.org>
permonik@mesias.brnonet.cz
Petar Marić <http://www.petarmaric.com/>
Pete Crosier <pete.crosier@gmail.com>
peter@mymart.com
Peter Sheats <sheats@gmail.com>
Peter van Kampen
Peter Zsoldos <http://zsoldosp.eu>
Pete Shinners <pete@shinners.org>
Petr Marhoun <petr.marhoun@gmail.com>
pgross@thoughtworks.com
phaedo <http://phaedo.cx/>
phil.h.smith@gmail.com
Philip Lindborg <philip.lindborg@gmail.com>
Philippe Raoult <philippe.raoult@n2nsoft.com>
phil@produxion.net
Piotr Jakimiak <piotr.jakimiak@gmail.com>
Piotr Lewandowski <piotr.lewandowski@gmail.com>
plisk
polpak@yahoo.com
pradeep.gowda@gmail.com
Preston Holmes <preston@ptone.com>
Preston Timmons <prestontimmons@gmail.com>
Priyansh Saxena <askpriyansh@gmail.com>
Przemysław Buczkowski <przemub@przemub.pl>
Przemysław Suliga <http://suligap.net>
Qi Zhao <zhaoqi99@outlook.com>
Rachel Tobin <rmtobin@me.com>
Rachel Willmer <http://www.willmer.com/kb/>
Radek Švarz <https://www.svarz.cz/translate/>
Raffaele Salmaso <raffaele@salmaso.org>
Rajesh Dhawan <rajesh.dhawan@gmail.com>
Ramez Ashraf <ramezashraf@gmail.com>
Ramin Farajpour Cami <ramin.blackhat@gmail.com>
Ramiro Morales <ramiro@rmorales.net>
Ramon Saraiva <ramonsaraiva@gmail.com>
Ram Rachum <ram@rachum.com>
Randy Barlow <randy@electronsweatshop.com>
Raphaël Barrois <raphael.barrois@m4x.org>
Raphael Michel <mail@raphaelmichel.de>
Raúl Cumplido <raulcumplido@gmail.com>
Rebecca Smith <rebkwok@gmail.com>
Remco Wendt <remco.wendt@gmail.com>
Renaud Parent <renaud.parent@gmail.com>
Renbi Yu <averybigant@gmail.com>
Reza Mohammadi <reza@zeerak.ir>
rhettg@gmail.com
Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com>
ricardojbarrios@gmail.com
Riccardo Di Virgilio
Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
Richard Davies <richard.davies@elastichosts.com>
Richard House <Richard.House@i-logue.com>
Rick Wagner <rwagner@physics.ucsd.edu>
Rigel Di Scala <rigel.discala@propylon.com>
Robert Coup
Robert Myers <myer0052@gmail.com>
Roberto Aguilar <roberto@baremetal.io>
Robert Rock Howard <http://djangomojo.com/>
Robert Wittams
Rob Golding-Day <rob@golding-day.com>
Rob Hudson <https://rob.cogit8.org/>
Rob Nguyen <tienrobertnguyenn@gmail.com>
Robin Munn <http://www.geekforgod.com/>
Rodrigo Pinheiro Marques de Araújo <fenrrir@gmail.com>
Romain Garrigues <romain.garrigues.cs@gmail.com>
Ronny Haryanto <https://ronny.haryan.to/>
Ross Poulton <ross@rossp.org>
Rozza <ross.lawley@gmail.com>
Rudolph Froger <rfroger@estrate.nl>
Rudy Mutter
Rune Rønde Laursen <runerl@skjoldhoej.dk>
Russell Cloran <russell@rucus.net>
Russell Keith-Magee <russell@keith-magee.com>
Russ Webber
Ryan Hall <ryanhall989@gmail.com>
ryankanno
Ryan Kelly <ryan@rfk.id.au>
Ryan Niemeyer <https://profiles.google.com/ryan.niemeyer/about>
Ryan Petrello <ryan@ryanpetrello.com>
Ryan Rubin <ryanmrubin@gmail.com>
Ryno Mathee <rmathee@gmail.com>
Sachin Jat <sanch.jat@gmail.com>
Sage M. Abdullah <https://github.com/laymonage>
Sam Newman <http://www.magpiebrain.com/>
Sander Dijkhuis <sander.dijkhuis@gmail.com>
Sanket Saurav <sanketsaurav@gmail.com>
Sanyam Khurana <sanyam.khurana01@gmail.com>
Sarthak Mehrish <sarthakmeh03@gmail.com>
schwank@gmail.com
Scot Hacker <shacker@birdhouse.org>
Scott Barr <scott@divisionbyzero.com.au>
Scott Fitsimones <scott@airgara.ge>
Scott Pashley <github@scottpashley.co.uk>
scott@staplefish.com
Sean Brant
Sebastian Hillig <sebastian.hillig@gmail.com>
Sebastian Spiegel <https://www.tivix.com/>
Segyo Myung <myungsekyo@gmail.com>
Selwin Ong <selwin@ui.co.id>
Sengtha Chay <sengtha@e-khmer.com>
Senko Rašić <senko.rasic@dobarkod.hr>
serbaut@gmail.com
Sergei Maertens <sergeimaertens@gmail.com>
Sergey Fedoseev <fedoseev.sergey@gmail.com>
Sergey Kolosov <m17.admin@gmail.com>
Seth Hill <sethrh@gmail.com>
Shai Berger <shai@platonix.com>
Shannon -jj Behrens <https://www.jjinux.com/>
Shawn Milochik <shawn@milochik.com>
Silvan Spross <silvan.spross@gmail.com>
Simeon Visser <http://simeonvisser.com>
Simon Blanchard
Simon Charette <charette.s@gmail.com>
Simon Greenhill <dev@simon.net.nz>
Simon Litchfield <simon@quo.com.au>
Simon Meers <simon@simonmeers.com>
Simon Williams
Simon Willison <simon@simonwillison.net>
Sjoerd Job Postmus
Slawek Mikula <slawek dot mikula at gmail dot com>
sloonz <simon.lipp@insa-lyon.fr>
smurf@smurf.noris.de
sopel
Srinivas Reddy Thatiparthy <thatiparthysreenivas@gmail.com>
Stanislas Guerra <stan@slashdev.me>
Stanislaus Madueke
Stanislav Karpov <work@stkrp.ru>
starrynight <cmorgh@gmail.com>
Stefan R. Filipek
Stefane Fermgier <sf@fermigier.com>
Stefano Rivera <stefano@rivera.za.net>
Stéphane Raimbault <stephane.raimbault@gmail.com>
Stephan Jaekel <steph@rdev.info>
Stephen Burrows <stephen.r.burrows@gmail.com>
Steven L. Smith (fvox13) <steven@stevenlsmith.com>
Steven Noorbergen (Xaroth) <xaroth+django@xaroth.nl>
Stuart Langridge <https://www.kryogenix.org/>
Subhav Gautam <subhavgautam@yahoo.co.uk>
Sujay S Kumar <sujay.skumar141295@gmail.com>
Sune Kirkeby <https://ibofobi.dk/>
Sung-Jin Hong <serialx.net@gmail.com>
SuperJared
Susan Tan <susan.tan.fleckerl@gmail.com>
Sutrisno Efendi <kangfend@gmail.com>
Swaroop C H <http://www.swaroopch.info>
Szilveszter Farkas <szilveszter.farkas@gmail.com>
Taavi Teska <taaviteska@gmail.com>
Tai Lee <real.human@mrmachine.net>
Takashi Matsuo <matsuo.takashi@gmail.com>
Tareque Hossain <http://www.codexn.com>
Taylor Mitchell <taylor.mitchell@gmail.com>
Terry Huang <terryh.tp@gmail.com>
thebjorn <bp@datakortet.no>
Thejaswi Puthraya <thejaswi.puthraya@gmail.com>
Thijs van Dien <thijs@vandien.net>
Thom Wiggers
Thomas Chaumeny <t.chaumeny@gmail.com>
Thomas Güttler <hv@tbz-pariv.de>
Thomas Kerpe <thomas@kerpe.net>
Thomas Sorrel
Thomas Steinacher <http://www.eggdrop.ch/>
Thomas Stromberg <tstromberg@google.com>
Thomas Tanner <tanner@gmx.net>
tibimicu@gmx.net
Tim Allen <tim@pyphilly.org>
Tim Givois <tim.givois.mendez@gmail.com>
Tim Graham <timograham@gmail.com>
Tim Heap <tim@timheap.me>
Tim Saylor <tim.saylor@gmail.com>
Tobias Kunze <rixx@cutebit.de>
Tobias McNulty <https://www.caktusgroup.com/blog/>
tobias@neuyork.de
Todd O'Bryan <toddobryan@mac.com>
Tom Carrick <https://www.carrick.eu>
Tom Christie <tom@tomchristie.com>
Tom Forbes <tom@tomforb.es>
Tom Insam
Tom Tobin
Tomáš Ehrlich <tomas.ehrlich@gmail.com>
Tomáš Kopeček <permonik@m6.cz>
Tome Cvitan <tome@cvitan.com>
Tomek Paczkowski <tomek@hauru.eu>
Tomer Chachamu
Tommy Beadle <tbeadle@gmail.com>
Tore Lundqvist <tore.lundqvist@gmail.com>
torne-django@wolfpuppy.org.uk
Travis Cline <travis.cline@gmail.com>
Travis Pinney
Travis Swicegood <travis@domain51.com>
Travis Terry <tdterry7@gmail.com>
Trevor Caira <trevor@caira.com>
Trey Long <trey@ktrl.com>
tstromberg@google.com
tt@gurgle.no
Tyler Tarabula <tyler.tarabula@gmail.com>
Tyson Clugg <tyson@clugg.net>
Tyson Tate <tyson@fallingbullets.com>
Unai Zalakain <unai@gisa-elkartea.org>
Valentina Mukhamedzhanova <umirra@gmail.com>
valtron
Vasiliy Stavenko <stavenko@gmail.com>
Vasil Vangelovski
Vibhu Agarwal <vibhu-agarwal.github.io>
Victor Andrée
viestards.lists@gmail.com
Viktor Danyliuk <v.v.danyliuk@gmail.com>
Ville Säävuori <https://www.unessa.net/>
Vinay Karanam <https://github.com/vinayinvicible>
Vinay Sajip <vinay_sajip@yahoo.co.uk>
Vincent Foley <vfoleybourgon@yahoo.ca>
Vinny Do <vdo.code@gmail.com>
Vitaly Babiy <vbabiy86@gmail.com>
Vladimir Kuzma <vladimirkuzma.ch@gmail.com>
Vlado <vlado@labath.org>
Vsevolod Solovyov
Vytis Banaitis <vytis.banaitis@gmail.com>
wam-djangobug@wamber.net
Wang Chun <wangchun@exoweb.net>
Warren Smith <warren@wandrsmith.net>
Waylan Limberg <waylan@gmail.com>
Wiktor Kołodziej <wiktor@pykonik.org>
Wiley Kestner <wiley.kestner@gmail.com>
Wiliam Alves de Souza <wiliamsouza83@gmail.com>
Will Ayd <william.ayd@icloud.com>
William Schwartz <wkschwartz@gmail.com>
Will Hardy <django@willhardy.com.au>
Wilson Miner <wminer@gmail.com>
Wim Glenn <hey@wimglenn.com>
wojtek
Xavier Francisco <xavier.n.francisco@gmail.com>
Xia Kai <https://blog.xiaket.org/>
Yann Fouillat <gagaro42@gmail.com>
Yann Malet
Yasushi Masuda <whosaysni@gmail.com>
ye7cakf02@sneakemail.com
ymasuda@ethercube.com
Yoong Kang Lim <yoongkang.lim@gmail.com>
Yusuke Miyazaki <miyazaki.dev@gmail.com>
Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
Zachary Voase <zacharyvoase@gmail.com>
Zach Liu <zachliu@gmail.com>
Zach Thompson <zthompson47@gmail.com>
Zain Memon
Zak Johnson <zakj@nox.cx>
Žan Anderle <zan.anderle@gmail.com>
Zbigniew Siciarz <zbigniew@siciarz.net>
zegor
Zeynel Özdemir <ozdemir.zynl@gmail.com>
Zlatko Mašek <zlatko.masek@gmail.com>
zriv <https://github.com/zriv>
<Please alphabetize new entries>
A big THANK YOU goes to:
Rob Curley and Ralph Gage for letting us open-source Django.
Frank Wiles for making excellent arguments for open-sourcing, and for
his sage sysadmin advice.
Ian Bicking for convincing Adrian to ditch code generation.
Mark Pilgrim for "Dive Into Python" (https://www.diveinto.org/python3/).
Guido van Rossum for creating Python.

27
dot_bash_it/vendor/github.com/django/django/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Django nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,265 @@
Django is licensed under the three-clause BSD license; see the file
LICENSE for details.
Django includes code from the Python standard library, which is licensed under
the Python license, a permissive open source license. The copyright and license
is included below for compliance with Python's terms.
----------------------------------------------------------------------
Copyright (c) 2001-present Python Software Foundation; All Rights Reserved
A. HISTORY OF THE SOFTWARE
==========================
Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
as a successor of a language called ABC. Guido remains Python's
principal author, although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.
In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
year, the PythonLabs team moved to Digital Creations, which became
Zope Corporation. In 2001, the Python Software Foundation (PSF, see
https://www.python.org/psf/) was formed, a non-profit organization
created specifically to own Python-related Intellectual Property.
Zope Corporation was a sponsoring member of the PSF.
All Python releases are Open Source (see http://www.opensource.org for
the Open Source Definition). Historically, most, but not all, Python
releases have also been GPL-compatible; the table below summarizes
the various releases.
Release Derived Year Owner GPL-
from compatible? (1)
0.9.0 thru 1.2 1991-1995 CWI yes
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
1.6 1.5.2 2000 CNRI no
2.0 1.6 2000 BeOpen.com no
1.6.1 1.6 2001 CNRI yes (2)
2.1 2.0+1.6.1 2001 PSF no
2.0.1 2.0+1.6.1 2001 PSF yes
2.1.1 2.1+2.0.1 2001 PSF yes
2.1.2 2.1.1 2002 PSF yes
2.1.3 2.1.2 2002 PSF yes
2.2 and above 2.1.1 2001-now PSF yes
Footnotes:
(1) GPL-compatible doesn't mean that we're distributing Python under
the GPL. All Python licenses, unlike the GPL, let you distribute
a modified version without making your changes open source. The
GPL-compatible licenses make it possible to combine Python with
other software that is released under the GPL; the others don't.
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
because its license has a choice of law clause. According to
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
is "not incompatible" with the GPL.
Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
===============================================================
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-------------------------------------------
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization ("Licensee") accessing and otherwise using
this software in source or binary form and its associated
documentation ("the Software").
2. Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.
3. BeOpen is making the Software available to Licensee on an "AS IS"
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
5. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
6. This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions. Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee. This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party. As an exception, the "BeOpen Python" logos available at
http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.
7. By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
---------------------------------------
1. This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 ("CNRI"), and the Individual or Organization
("Licensee") accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.
2. Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
1995-2001 Corporation for National Research Initiatives; All Rights
Reserved" are retained in Python 1.6.1 alone or in any derivative
version prepared by Licensee. Alternately, in lieu of CNRI's License
Agreement, Licensee may substitute the following text (omitting the
quotes): "Python 1.6.1 is made available subject to the terms and
conditions in CNRI's License Agreement. This Agreement together with
Python 1.6.1 may be located on the Internet using the following
unique, persistent identifier (known as a handle): 1895.22/1013. This
Agreement may also be obtained from a proxy server on the Internet
using the following URL: http://hdl.handle.net/1895.22/1013".
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee. This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.
8. By clicking on the "ACCEPT" button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.
ACCEPT
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
--------------------------------------------------
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
The Netherlands. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,9 @@
all: sdist bdist_wheel
sdist:
python setup.py sdist
bdist_wheel:
python setup.py bdist_wheel
.PHONY : sdist bdist_wheel

View File

@@ -0,0 +1 @@
This directory contains extra stuff that can improve your Django experience.

View File

@@ -0,0 +1,71 @@
# #############################################################################
# This bash script adds tab-completion feature to django-admin and manage.py.
#
# Testing it out without installing
# =================================
#
# To test out the completion without "installing" this, just run this file
# directly, like so:
#
# . ~/path/to/django_bash_completion
#
# Note: There's a dot ('.') at the beginning of that command.
#
# After you do that, tab completion will immediately be made available in your
# current Bash shell. But it won't be available next time you log in.
#
# Installing
# ==========
#
# To install this, point to this file from your .bash_profile, like so:
#
# . ~/path/to/django_bash_completion
#
# Do the same in your .bashrc if .bashrc doesn't invoke .bash_profile.
#
# Settings will take effect the next time you log in.
#
# Uninstalling
# ============
#
# To uninstall, just remove the line from your .bash_profile and .bashrc.
_django_completion()
{
COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \
COMP_CWORD=$COMP_CWORD \
DJANGO_AUTO_COMPLETE=1 $1 ) )
}
# When the django-admin.py deprecation ends, remove django-admin.py.
complete -F _django_completion -o default django-admin.py manage.py django-admin
_python_django_completion()
{
if [[ ${COMP_CWORD} -ge 2 ]]; then
local PYTHON_EXE=${COMP_WORDS[0]##*/}
if echo "$PYTHON_EXE" | grep -qE "python([3-9]\.[0-9])?"; then
local PYTHON_SCRIPT=${COMP_WORDS[1]##*/}
if echo "$PYTHON_SCRIPT" | grep -qE "manage\.py|django-admin(\.py)?"; then
COMPREPLY=( $( COMP_WORDS=( "${COMP_WORDS[*]:1}" )
COMP_CWORD=$(( COMP_CWORD-1 ))
DJANGO_AUTO_COMPLETE=1 ${COMP_WORDS[*]} ) )
fi
fi
fi
}
# Support for multiple interpreters.
unset pythons
if command -v whereis &>/dev/null; then
python_interpreters=$(whereis python | cut -d " " -f 2-)
for python in $python_interpreters; do
[[ $python != *-config ]] && pythons="${pythons} ${python##*/}"
done
unset python_interpreters
pythons=$(echo "$pythons" | tr " " "\n" | sort -u | tr "\n" " ")
else
pythons=python
fi
complete -F _python_django_completion -o default $pythons
unset pythons

View File

@@ -0,0 +1,90 @@
1.3 / 2015-11-04
==================
* Make glossary() faster by not introspecting loaded shell functions
* Remove brittle and incomplete test suite
* Fixes for shellcheck.net
1.2.4 / 2015-08-29
==================
* Minor updates for latest shellcheck.net codes
* Fix write() function, thanks @IsoLinearCHiP!
1.2.3 / 2015-04-01
==================
* Minor fixes for latest shellcheck.net codes
* Better wrapping for long about metadata
* Support leading hyphens in function names
1.2.2 / 2015-01-16
==================
various fixes, including contributions from:
* @nilbus
* @martinlauer
* @DrVanScott
1.2.1 / 2014-01-05
==================
* Tab completion for revise(), new compost() func
* Improve shell determination and bootstrapping sequence
1.2.0 / 2013-11-17
==================
* Auto-load composed functions
1.1.1 / 2013-10-29
==================
* Fix issue with zsh noclobber option
1.1.0 / 2013-10-23
==================
* Auto-revise drafted functions
* Populate author metadata on draft
* Use tpope-style commit msgs
* Respect XDG_DATA_HOME
1.0.4 / 2013-08-30
==================
* increase letterpress spacing
* refactor composure extras
1.0.3 / 2012-11-29
==================
* make revise() smarter
* write() includes shebang and main() invocation
1.0.2 / 2012-05-24
==================
* use _plumbing nomenclature
1.0.1 / 2012-05-19
==================
* revise() takes an optional -e flag
* revise() aborts on an empty file
* metadata cleaned up
1.0 / 2012-05-17
==================
* performance improvements
* fix draft(): ensure alias names are not used for function names
* porcelain is self-referential
* consolidate plumbing fns
* add diagram
* write() porcelain
* apidoc for author & version
* second-order functions
* asciicast demo!
* prompt for git repo creation
* full POSIX compatibility
* revised documentation
* sed-fu rescues case blocks - solves #1
* basic git tracking
* remove hyphens from function names
* fix for non-interactive shells
* respect EDITOR preference
* add readme
* initial commit

16
dot_bash_it/vendor/github.com/erichs/composure/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,16 @@
License: The MIT License
Copyright © 2012, 2016 Erich Smith
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,10 @@
TARGET = tests
all: $(TARGET)
tests:
cd test && make tests
clean::
rm -f test/*~ test/t/*~
rm -rf test/composure_test

View File

@@ -0,0 +1,242 @@
e88~~\ e88~-_ 888-~88e-~88e 888-~88e e88~-_ d88~\ 888 888 888-~\ e88~~8e
d888 d888 i 888 888 888 888 888b d888 i C888 888 888 888 d888 88b
8888 8888 | 888 888 888 888 8888 8888 | Y88b 888 888 888 8888__888
Y888 Y888 ' 888 888 888 888 888P Y888 ' 888D 888 888 888 Y888 ,
"88__/ "88_-~ 888 888 888 888-_88" "88_-~ \_88P "88_-888 888 "88___/
888
# Composure: don't fear the Unix chainsaw
These light-hearted functions make programming the shell easier and
more intuitive:
* Transition organically from command, to function, to script
* Use an unobtrusive help system with arbitrary shell metadata
* Automatically version and store your shell functions with Git
static analysis and automated tests: [![Build Status](https://travis-ci.org/erichs/composure.png?branch=master)](https://travis-ci.org/erichs/composure)
## Demo!
[Composing a simple network monitoring script](http://asciinema.org/a/476) (4 minutes)
## Compatibility
Composure is POSIX-compliant, and is known to work on ksh93, zsh, and
bash, on osx and linux.
Please feel free to open an issue if you have any difficulties on your system.
## Installing
Put composure.sh where you'd like it to live and source it from your
shell's profile or rc file.
On Bash:
```bash
cd /your/favorite/directory
curl -L http://git.io/composure > composure.sh
chmod +x composure.sh
echo "source $(pwd)/composure.sh" >> ~/.bashrc # or, ~/.bash_profile on osx
```
Users upgrading from a version prior to 1.1.0 need to execute the following commands, as the directory for composure's local repo has changed:
```bash
mkdir ~/.local 2>/dev/null
mv ~/.composure ~/.local/composure
```
## Craft - Draft - Revise - Write
<img src="http://yuml.me/47fcf7e2" />
### Crafting the command line
[REPL environments](http://repl.it) are great for trying out programming ideas
and crafting snippets of working code, aren't they? Composure helps you make
better use of the REPL environment constantly at your fingertips: the shell.
Many Unix users I know like to iteratively build up complex commands by trying
something out, hitting the up arrow and perhaps adding a filter with a pipe:
```bash
$ cat servers.txt
bashful: up
doc: down
up-arrow
$ cat servers.txt | grep down
doc: down
up-arrow
$ cat servers.txt | grep down | mail -s "down server(s)" admin@here.com
```
Composure helps by letting you quickly draft simple shell functions, breaking down
your long pipe filters and complex commands into readable and reusable chunks.
### Draft first, ask questions later
Once you've crafted your gem of a command, don't throw it away! Use 'draft ()'
and give it a [good name](http://martinfowler.com/bliki/TwoHardThings.html).
This stores your last command as a function you can reuse later. Think of it
like a rough draft.
```bash
$ cat servers.txt
bashful: up
doc: down
up-arrow
$ cat servers.txt | grep down
doc: down
$ draft finddown
$ finddown | mail -s "down server(s)" admin@here.com
```
### Revise, revise, revise!
Now that you've got a minimal shell function, you may want to make it better
through refactoring and revision. Use the 'revise ()' command to revise your
shell function in your favorite editor.
* generalize functions with input parameters
* add or remove functionality
* add supporting metadata for documentation
```bash
$ revise finddown
finddown ()
{
about finds servers marked 'down' in text file
group admin
cat $1 | grep down
}
$ finddown servers.txt
doc: down
```
### Get it in Writing
When it is time to put your function or functions to use in a shell script, just call write:
```bash
$ write finddown > finddown.sh
```
Edit the main() function, chmod +x, and you're ready to go!
## Arbitrary shell metadata!
Composure uses a simple system of dynamic keywords that allow you to add
metadata to your functions. Just call 'cite ()' to initialize your new
keyword(s), and use them freely in your functions:
```bash
foo()
{
cite about
about perform mad script-foo
echo 'foo'
}
```
Retrieve your metadata later by calling 'metafor ()':
```bash
typeset -f foo | metafor about # displays:
perform mad script-foo
```
By default, composure knows the keywords: about, param, group, author, and example.
These default keywords are used by the help system:
## Intuitive help system
The 'glossary ()' function will automatically summarize all functions with
'about' metadata. If called with a 'group' name as a parameter, it will
summarize functions belonging to that group.
To display apidoc-style help for a function, use 'reference ()'.
```bash
$ glossary # displays:
cite creates a new meta keyword for use in your functions
draft wraps last command into a new function
finddown finds servers marked 'down' in text file
foo perform mad script-foo
glossary displays help summary for all functions, or summary for a group of functions
metafor prints function metadata associated with keyword
reference displays apidoc help for a specific function
revise loads function into editor for revision
write writes one or more composed function definitions to stdout
meanwhile
$ glossary admin # displays:
finddown finds servers marked 'down' in text file
and
$ reference draft # displays:
draft wraps last command into a new function
parameters:
1: name to give function
examples:
$ ls
$ draft list
$ list
```
## Git integration
If you already use git, installing composure will initialize a ~/.local/composure
repository, and store and version your functions there. Just use 'draft ()' and
'revise ()', they automatically version for you.
Composure supports the [XDG Base Directory](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html)
specification, and will respect your local XDG_DATA_HOME environment variable.
Why do this?
* the latest version of any function you've composed may always be sourced from
your composure repo
* never throw away code--keep your one-off functions in your composure 'junk
drawer', and grep through it later for long-forgotten gems
* every version of every function you write is always
available to you via basic git commands
## Persistent access
Draft or revise a function, and the latest version is automatically sourced into your current shell environment. By default, composure automatically sources all of your composed functions when you source the composure.sh script. If you are concerned about shell startup time, have many hundreds of versioned shell functions, or otherwise want to control which functions are loaded from your composure repository, you may disable the default behavior by adding the following line to your shell's startup script:
```shell
export LOAD_COMPOSED_FUNCTIONS=0
```
# Credits
Composure grew out of ideas taken from from Gary Bernhardt's hilarious talk [The Unix
Chainsaw](http://www.confreaks.com/videos/615-cascadiaruby2011-the-unix-chainsaw) (31 minutes),
which refers to the Elements of Programming described in MIT's [SICP
text](http://mitpress.mit.edu/sicp/full-text/book/book.html):
* primitive expressions
* means of combination
* means of abstraction
## Known Issues
'glossary ()' and 'reference ()' do not support nested functions with metadata.
`revise` works well if your editor is terminal-based, like Emacs or Vim. If you use a windowed editor like Atom, VSCode, or Sublime, you will need to check to see if your editor supports a flag argument that allows it to wait for the files to be closed before returning. If this is supported, you can create a small script to launch your editor in this mode, and specify that script path in your `EDITOR` var. See https://github.com/erichs/composure/issues/10.

View File

@@ -0,0 +1,145 @@
#!/bin/bash
_basename_no_extension () {
sed -e 's/^.*\/\(.*\)\.inc$/\1/'
}
_composure_functions () {
_list_composure_files | _basename_no_extension
}
_load_tab_completions () {
# support tab completion for 'revise' command
# you may disable this by adding the following line to your shell startup:
# export COMPOSURE_TAB_COMPLETION=0
if [ "$COMPOSURE_TAB_COMPLETION" = "0" ]; then
return # if you say so...
fi
case "$(_shell)" in
zsh)
read -r -d '' SCRIPT <<ZSHDATA
_zsh_revise_complete () {
typeset word completions
word="\$1"
completions="\$(_composure_functions)"
reply=( "\${(ps:\n:)completions}" )
}
compctl -K _zsh_revise_complete revise
ZSHDATA
eval "$SCRIPT"
unset SCRIPT
;;
bash)
read -r -d '' SCRIPT <<BASHDATA
_bash_revise_complete () {
typeset cur
cur=\${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( \$(compgen -W "\$(_composure_functions)" -- \$cur) )
return 0
}
complete -F _bash_revise_complete revise
BASHDATA
eval "$SCRIPT"
unset SCRIPT
;;
*)
echo "composure tab completions unavailable"
;;
esac
}
# Second-order functions for composure
findgroup ()
{
about 'finds all functions belonging to group'
param '1: name of group'
example '$ findgroup tools'
group 'composure'
typeset func
for func in $(_typeset_functions)
do
typeset group="$(typeset -f $func | metafor group)"
if [ "$group" = "$1" ]; then
echo "$func"
fi
done
}
overview ()
{
about 'gives overview of available shell functions, by group'
group 'composure'
# display a brief progress message...
printf '%s' 'building documentation...'
typeset grouplist=$(mktemp /tmp/grouplist.XXXX);
typeset func;
for func in $(_typeset_functions);
do
typeset group="$(typeset -f $func | metafor group)";
if [ -z "$group" ]; then
group='misc';
fi;
typeset about="$(typeset -f $func | metafor about)";
_letterpress "$about" $func >> $grouplist.$group;
echo $grouplist.$group >> $grouplist;
done;
# clear progress message
printf '\r%s\n' ' '
typeset group;
typeset gfile;
for gfile in $(cat $grouplist | sort | uniq);
do
printf '%s\n' "${gfile##*.}:";
cat $gfile;
printf '\n';
command rm $gfile 2> /dev/null;
done | less
command rm $grouplist 2> /dev/null
}
recompose ()
{
about 'loads a stored function from ~/.composure repo'
param '1: name of function'
example '$ load myfunc'
group 'composure'
. $(_get_composure_dir)/$1.inc
}
unique_metafor ()
{
about 'displays all unique metadata for a given keyword'
param '1: keyword'
example '$ unique_metafor group'
group 'composure'
typeset keyword=$1
typeset file=$(mktemp /tmp/composure.XXXX)
typeset -f | metafor $keyword >> $file
cat $file | sort | uniq
command rm $file 2>/dev/null
}
compost () {
about 'delete function stored in composure repo'
param '1: name of function'
example '$ compost myfunc'
group 'composure'
typeset func=$1
[ -z "$func" ] && echo "you must specify a function name!" && return 1
(
cd $(_get_composure_dir)
git rm "$func.inc" && git commit -m "Delete function $func"
)
}
_load_tab_completions

View File

@@ -0,0 +1,2 @@
#!/bin/zsh
source ${0:h}/{composure,c_extras}.sh

View File

@@ -0,0 +1 @@
composure_test/**

View File

@@ -0,0 +1,9 @@
language: c
script: make tests
branches:
only:
- testing
- master
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq ksh zsh

View File

@@ -0,0 +1,561 @@
#!/bin/bash
# composure - by erichs
# light-hearted functions for intuitive shell programming
# version: 1.3.1
# latest source available at http://git.io/composure
# install: source this script in your ~/.profile or ~/.${SHELL}rc script
# known to work on bash, zsh, and ksh93
# 'plumbing' functions
_bootstrap_composure() {
_generate_metadata_functions
_load_composed_functions
_determine_printf_cmd
}
_get_composure_dir ()
{
if [ -n "${XDG_DATA_HOME:-}" ]; then
echo "$XDG_DATA_HOME/composure"
else
echo "$HOME/.local/composure"
fi
}
_get_author_name ()
{
typeset name localname
localname="$(git --git-dir "$(_get_composure_dir)/.git" config --get user.name)"
for name in "${GIT_AUTHOR_NAME:-}" "$localname"; do
if [ -n "$name" ]; then
echo "$name"
break
fi
done
}
_composure_keywords ()
{
echo "about author example group param version"
}
_letterpress ()
{
typeset rightcol="$1" leftcol="${2:- }" leftwidth="${3:-20}"
if [ -z "$rightcol" ]; then
return
fi
$_printf_cmd "%-*s%s\n" "$leftwidth" "$leftcol" "$rightcol"
}
_determine_printf_cmd() {
if [ -z "${_printf_cmd:-}" ]; then
_printf_cmd=printf
# prefer GNU gprintf if available
[ -x "$(which gprintf 2>/dev/null)" ] && _printf_cmd=gprintf
export _printf_cmd
fi
}
_longest_function_name_length ()
{
echo "$1" | awk 'BEGIN{ maxlength=0 }
{
for(i=1;i<=NF;i++)
if (length($i)>maxlength)
{
maxlength=length($i)
}
}
END{ print maxlength}'
}
_temp_filename_for ()
{
typeset file="$(mktemp "/tmp/$1.XXXX")"
command rm "$file" 2>/dev/null # ensure file is unlinked prior to use
echo "$file"
}
_prompt ()
{
typeset prompt="$1"
typeset result
case "$(_shell)" in
bash)
read -r -e -p "$prompt" result;;
*)
echo -n "$prompt" >&2; read -r result;;
esac
echo "$result"
}
_add_composure_file ()
{
typeset func="$1"
typeset file="$2"
typeset operation="$3"
typeset comment="${4:-}"
typeset composure_dir=$(_get_composure_dir)
(
if ! cd "$composure_dir"; then
printf "%s\n" "Oops! Can't find $composure_dir!"
return
fi
if git rev-parse 2>/dev/null; then
if [ ! -f "$file" ]; then
printf "%s\n" "Oops! Couldn't find $file to version it for you..."
return
fi
cp "$file" "$composure_dir/$func.inc"
git add --all .
if [ -z "$comment" ]; then
comment="$(_prompt 'Git Comment: ')"
fi
git commit -m "$operation $func: $comment"
fi
)
}
_transcribe ()
{
typeset func="$1"
typeset file="$2"
typeset operation="$3"
typeset comment="${4:-}"
typeset composure_dir=$(_get_composure_dir)
if git --version >/dev/null 2>&1; then
if [ -d "$composure_dir" ]; then
_add_composure_file "$func" "$file" "$operation" "$comment"
else
if [ "${USE_COMPOSURE_REPO:-}" = "0" ]; then
return # if you say so...
fi
printf "%s\n" "I see you don't have a $composure_dir repo..."
typeset input=''
typeset valid=0
while [ $valid != 1 ]; do
printf "\n%s" 'would you like to create one? y/n: '
read -r input
case $input in
y|yes|Y|Yes|YES)
(
echo 'creating git repository for your functions...'
mkdir -p "$composure_dir" || return 1
cd "$composure_dir" || return 1
git init
echo "composure stores your function definitions here" > README.txt
git add README.txt
git commit -m 'initial commit'
)
# if at first you don't succeed...
_transcribe "$func" "$file" "$operation" "$comment"
valid=1
;;
n|no|N|No|NO)
printf "%s\n" "ok. add 'export USE_COMPOSURE_REPO=0' to your startup script to disable this message."
valid=1
;;
*)
printf "%s\n" "sorry, didn't get that..."
;;
esac
done
fi
fi
}
_typeset_functions ()
{
# unfortunately, there does not seem to be a easy, portable way to list just the
# names of the defined shell functions...
case "$(_shell)" in
sh|bash)
typeset -F | awk '{print $3}'
;;
*)
# trim everything following '()' in ksh/zsh
typeset +f | sed 's/().*$//'
;;
esac
}
_typeset_functions_about ()
{
typeset f
for f in $(_typeset_functions); do
typeset -f -- "$f" | grep -qE "^about[[:space:]]|[[:space:]]about[[:space:]]" && echo -- "$f"
done
}
_shell () {
# here's a hack I modified from a StackOverflow post:
# get the ps listing for the current process ($$), and print the last column (CMD)
# stripping any leading hyphens shells sometimes throw in there
typeset this=$(ps -o comm -p $$ | tail -1 | awk '{print $NF}' | sed 's/^-*//')
echo "${this##*/}" # e.g. /bin/bash => bash
}
_generate_metadata_functions() {
typeset f
for f in $(_composure_keywords)
do
eval "$f() { :; }"
done
}
_list_composure_files () {
typeset composure_dir="$(_get_composure_dir)"
[ -d "$composure_dir" ] && find "$composure_dir" -maxdepth 1 -name '*.inc'
}
_load_composed_functions () {
# load previously composed functions into shell
# you may disable this by adding the following line to your shell startup:
# export LOAD_COMPOSED_FUNCTIONS=0
if [ "${LOAD_COMPOSED_FUNCTIONS:-}" = "0" ]; then
return # if you say so...
fi
typeset inc
for inc in $(_list_composure_files); do
# shellcheck source=/dev/null
. "$inc"
done
}
_strip_trailing_whitespace () {
sed -e 's/ \+$//'
}
_strip_semicolons () {
sed -e 's/;$//'
}
# 'porcelain' functions
cite ()
{
about 'creates one or more meta keywords for use in your functions'
param 'one or more keywords'
example '$ cite url username'
example '$ url http://somewhere.com'
example '$ username alice'
group 'composure'
# this is the storage half of the 'metadata' system:
# we create dynamic metadata keywords with function wrappers around
# the NOP command, ':'
# anything following a keyword will get parsed as a positional
# parameter, but stay resident in the ENV. As opposed to shell
# comments, '#', which do not get parsed and are not available
# at runtime.
# a BIG caveat--your metadata must be roughly parsable: do not use
# contractions, and consider single or double quoting if it contains
# non-alphanumeric characters
if [ -z "$1" ]; then
printf '%s\n' 'missing parameter(s)'
reference cite
return
fi
typeset keyword
for keyword in "$@"; do
eval "$keyword() { :; }"
done
}
draft ()
{
about 'wraps command from history into a new function, default is last command'
param '1: name to give function'
param '2: optional history line number'
example '$ ls'
example '$ draft list'
example '$ draft newfunc 1120 # wraps command at history line 1120 in newfunc()'
group 'composure'
typeset func=$1
typeset num=$2
if [ -z "$func" ]; then
printf '%s\n' 'missing parameter(s)'
reference draft
return
fi
# aliases bind tighter than function names, disallow them
if type -a "$func" 2>/dev/null | grep -q 'is.*alias'; then
printf '%s\n' "sorry, $(type -a "$func"). please choose another name."
return
fi
typeset cmd
if [ -z "$num" ]; then
# some versions of 'fix command, fc' need corrective lenses...
typeset lines=$(fc -ln -1 | grep -q draft && echo 2 || echo 1)
# parse last command from fc output
# shellcheck disable=SC2086
cmd=$(fc -ln -$lines | head -1 | sed 's/^[[:blank:]]*//')
else
# parse command from history line number
cmd=$(eval "history | grep '^[[:blank:]]*$num' | head -1" | sed 's/^[[:blank:][:digit:]]*//')
fi
eval "function $func {
author '$(_get_author_name)'
about ''
param ''
example ''
group ''
$cmd;
}"
typeset file=$(_temp_filename_for draft)
typeset -f "$func" | _strip_trailing_whitespace | _strip_semicolons > "$file"
_transcribe "$func" "$file" Draft "Initial draft"
command rm "$file" 2>/dev/null
revise "$func"
}
glossary ()
{
about 'displays help summary for all functions, or summary for a group of functions'
param '1: optional, group name'
example '$ glossary'
example '$ glossary misc'
group 'composure'
typeset targetgroup=${1:-}
typeset functionlist="$(_typeset_functions_about)"
typeset maxwidth=$(_longest_function_name_length "$functionlist" | awk '{print $1 + 5}')
for func in $(echo $functionlist); do
if [ "X${targetgroup}X" != "XX" ]; then
typeset group="$(typeset -f -- $func | metafor group)"
if [ "$group" != "$targetgroup" ]; then
continue # skip non-matching groups, if specified
fi
fi
typeset about="$(typeset -f -- $func | metafor about)"
typeset aboutline=
echo "$about" | fmt | while read -r aboutline; do
_letterpress "$aboutline" "$func" "$maxwidth"
func=" " # only display function name once
done
done
}
metafor ()
{
about 'prints function metadata associated with keyword'
param '1: meta keyword'
example '$ typeset -f glossary | metafor example'
group 'composure'
typeset keyword=$1
if [ -z "$keyword" ]; then
printf '%s\n' 'missing parameter(s)'
reference metafor
return
fi
# this sed-fu is the retrieval half of the 'metadata' system:
# 'grep' for the metadata keyword, and then parse/filter the matching line
# grep keyword # strip trailing '|"|; # ignore thru keyword and leading '|"
sed -n "/$keyword / s/['\";]*\$//;s/^[ ]*\(: _\)*$keyword ['\"]*\([^([].*\)*\$/\2/p"
}
reference ()
{
about 'displays apidoc help for a specific function'
param '1: function name'
example '$ reference revise'
group 'composure'
typeset func=$1
if [ -z "$func" ]; then
printf '%s\n' 'missing parameter(s)'
reference reference
return
fi
typeset line
typeset about="$(typeset -f "$func" | metafor about)"
_letterpress "$about" "$func"
typeset author="$(typeset -f $func | metafor author)"
if [ -n "$author" ]; then
_letterpress "$author" 'author:'
fi
typeset version="$(typeset -f $func | metafor version)"
if [ -n "$version" ]; then
_letterpress "$version" 'version:'
fi
if [ -n "$(typeset -f $func | metafor param)" ]; then
printf "parameters:\n"
typeset -f $func | metafor param | while read -r line
do
_letterpress "$line"
done
fi
if [ -n "$(typeset -f $func | metafor example)" ]; then
printf "examples:\n"
typeset -f $func | metafor example | while read -r line
do
_letterpress "$line"
done
fi
}
revise ()
{
about 'loads function into editor for revision'
param '<optional> -e: revise version stored in ENV'
param '1: name of function'
example '$ revise myfunction'
example '$ revise -e myfunction'
example 'save a zero-length file to abort revision'
group 'composure'
typeset source='git'
if [ "$1" = '-e' ]; then
source='env'
shift
fi
typeset func=$1
if [ -z "$func" ]; then
printf '%s\n' 'missing parameter(s)'
reference revise
return
fi
typeset composure_dir=$(_get_composure_dir)
typeset temp=$(_temp_filename_for revise)
# populate tempfile...
if [ "$source" = 'env' ] || [ ! -f "$composure_dir/$func.inc" ]; then
# ...with ENV if specified or not previously versioned
typeset -f $func > $temp
else
# ...or with contents of latest git revision
cat "$composure_dir/$func.inc" > "$temp"
fi
if [ -z "${EDITOR:-}" ]
then
typeset EDITOR=vi
fi
$EDITOR "$temp"
if [ -s "$temp" ]; then
typeset edit='N'
# source edited file
# shellcheck source=/dev/null
. "$temp" || edit='Y'
while [ $edit = 'Y' ]; do
echo -n "Re-edit? Y/N: "
read -r edit
case $edit in
y|yes|Y|Yes|YES)
edit='Y'
$EDITOR "$temp"
# shellcheck source=/dev/null
. "$temp" && edit='N';;
*)
edit='N';;
esac
done
_transcribe "$func" "$temp" Revise
else
# zero-length files abort revision
printf '%s\n' 'zero-length file, revision aborted!'
fi
command rm "$temp"
}
write ()
{
about 'writes one or more composed function definitions to stdout'
param 'one or more function names'
example '$ write finddown foo'
example '$ write finddown'
group 'composure'
if [ -z "$1" ]; then
printf '%s\n' 'missing parameter(s)'
reference write
return
fi
echo "#!/usr/bin/env ${SHELL##*/}"
# bootstrap metadata
cat <<END
for f in $(_composure_keywords)
do
eval "\$f() { :; }"
done
unset f
END
# write out function definitons
# shellcheck disable=SC2034
typeset -f cite "$@"
cat <<END
main() {
echo "edit me to do something useful!"
exit 0
}
main \$*
END
}
_bootstrap_composure
: <<EOF
License: The MIT License
Copyright © 2012, 2016 Erich Smith
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
EOF

View File

@@ -0,0 +1,18 @@
TARGET = tests
all: $(TARGET)
runtests:
./runtests.sh
runshellcheck:
./runshellcheck.sh
tests:
./wvtestrun $(MAKE) runshellcheck
clean::
rm -f *~ t/*~
rm -rf composure_test

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env sh
# run code quality metrics
echo "Testing \"code quality\" with shellcheck.net in ../composure.sh:"
datafile=shellcheck.raw
metricfile=shellcheck.out
curl -s --data-urlencode script="$(cat ../composure.sh)" \
www.shellcheck.net/shellcheck.php > $datafile
cat $datafile | python -mjson.tool > $metricfile
rm $datafile
cat $metricfile
# check for shellcheck.net errors
cat $metricfile | grep -q error
if [ $? -eq 0 ]; then
echo "! shellcheck.net:../composure.sh:0 [ errors ] FAILED"
rm $metricfile
exit 2
fi
# check for shellcheck.net warnings
cat $metricfile | grep -q warning
if [ $? -eq 0 ]; then
echo "! shellcheck.net:../composure.sh:0 [ warnings ] FAILED"
rm $metricfile
exit 2
fi
echo "! shellcheck.net:../composure.sh:0 [ no errors or warnings ] ok"
rm $metricfile

View File

@@ -0,0 +1,189 @@
#!/usr/bin/perl -w
#
# WvTest:
# Copyright (C)2007-2012 Versabanq Innovations Inc. and contributors.
# Licensed under the GNU Library General Public License, version 2.
# See the included file named LICENSE for license information.
# You can get wvtest from: http://github.com/apenwarr/wvtest
#
use strict;
use Time::HiRes qw(time);
# always flush
$| = 1;
if (@ARGV < 1) {
print STDERR "Usage: $0 <command line...>\n";
exit 127;
}
print STDERR "Testing \"all\" in @ARGV:\n";
my $pid = open(my $fh, "-|");
if (!$pid) {
# child
setpgrp();
open STDERR, '>&STDOUT' or die("Can't dup stdout: $!\n");
exec(@ARGV);
exit 126; # just in case
}
my $istty = -t STDOUT && $ENV{'TERM'} ne "dumb";
my @log = ();
my ($gpasses, $gfails) = (0,0);
sub bigkill($)
{
my $pid = shift;
if (@log) {
print "\n" . join("\n", @log) . "\n";
}
print STDERR "\n! Killed by signal FAILED\n";
($pid > 0) || die("pid is '$pid'?!\n");
local $SIG{CHLD} = sub { }; # this will wake us from sleep() faster
kill 15, $pid;
sleep(2);
if ($pid > 1) {
kill 9, -$pid;
}
kill 9, $pid;
exit(125);
}
# parent
local $SIG{INT} = sub { bigkill($pid); };
local $SIG{TERM} = sub { bigkill($pid); };
local $SIG{ALRM} = sub {
print STDERR "Alarm timed out! No test results for too long.\n";
bigkill($pid);
};
sub colourize($)
{
my $result = shift;
my $pass = ($result eq "ok");
if ($istty) {
my $colour = $pass ? "\e[32;1m" : "\e[31;1m";
return "$colour$result\e[0m";
} else {
return $result;
}
}
sub mstime($$$)
{
my ($floatsec, $warntime, $badtime) = @_;
my $ms = int($floatsec * 1000);
my $str = sprintf("%d.%03ds", $ms/1000, $ms % 1000);
if ($istty && $ms > $badtime) {
return "\e[31;1m$str\e[0m";
} elsif ($istty && $ms > $warntime) {
return "\e[33;1m$str\e[0m";
} else {
return "$str";
}
}
sub resultline($$)
{
my ($name, $result) = @_;
return sprintf("! %-65s %s", $name, colourize($result));
}
my $allstart = time();
my ($start, $stop);
sub endsect()
{
$stop = time();
if ($start) {
printf " %s %s\n", mstime($stop - $start, 500, 1000), colourize("ok");
}
}
while (<$fh>)
{
chomp;
s/\r//g;
if (/^\s*Testing "(.*)" with (.*) in (.*):\s*$/)
{
alarm(120);
my ($sect, $shell, $file) = ($1, $2, $3);
endsect();
chomp($shell=`basename $shell`);
printf("! %s %s %s: ", $shell, $file, $sect);
@log = ();
$start = $stop;
}
elsif (/^!\s*(.*?)\s+(\S+)\s*$/)
{
alarm(120);
my ($name, $result) = ($1, $2);
my $pass = ($result eq "ok");
if (!$start) {
printf("\n! Startup: ");
$start = time();
}
push @log, resultline($name, $result);
if (!$pass) {
$gfails++;
if (@log) {
print "\n" . join("\n", @log) . "\n";
@log = ();
}
} else {
$gpasses++;
print ".";
}
}
else
{
push @log, $_;
}
}
endsect();
my $newpid = waitpid($pid, 0);
if ($newpid != $pid) {
die("waitpid returned '$newpid', expected '$pid'\n");
}
my $code = $?;
my $ret = ($code >> 8);
# return death-from-signal exits as >128. This is what bash does if you ran
# the program directly.
if ($code && !$ret) { $ret = $code | 128; }
if ($ret && @log) {
print "\n" . join("\n", @log) . "\n";
}
if ($code != 0) {
print resultline("Program returned non-zero exit code ($ret)", "FAILED");
}
my $gtotal = $gpasses+$gfails;
printf("\nWvTest: %d test%s, %d failure%s, total time %s.\n",
$gtotal, $gtotal==1 ? "" : "s",
$gfails, $gfails==1 ? "" : "s",
mstime(time() - $allstart, 2000, 5000));
print STDERR "\nWvTest result code: $ret\n";
exit( $ret ? $ret : ($gfails ? 125 : 0) );

View File

@@ -0,0 +1,30 @@
BSD 3-Clause License
Copyright (c) 2006, Playhaus
Copyright (c) 2021, gaelicWizard.LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,286 @@
# shellcheck shell=bash
# shellcheck disable=SC2207
#
# Bash command line completion for defaults
#
# Version 1.0 created by Jonathon Mah on 2006-11-08.
# Version 2.0 written by John Pell on 2021-09-11.
#
function matchpattern()
{
local PATTERN=${2:?$FUNCNAME: a pattern is required}
local SEP=${3:-|}
[[ -z "${PATTERN##*${SEP}${1}${SEP}*}" ]]
}
function _defaults_verbs()
{
local IFS=$'\n' # Treat only newlines as delimiters in string operations.
local LC_CTYPE='C' # Do not consider character set in string operations.
local LC_COLLATE='C' # Do not consider character set in pattern matching.
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD - 1]}"
COMPREPLY=()
case $COMP_CWORD in
1)
candidates=("${cmds// /$IFS}" "${host_opts[@]}")
;;
2 | 3)
candidates=("${cmds// /$IFS}")
;;
*)
return 1
;;
esac
COMPREPLY=($(compgen -W "${candidates[*]}" | grep -i "^${cur}"))
return 0
}
function _defaults_domains()
{
local IFS=$'\n' # Treat only newlines as delimiters in string operations.
local LC_CTYPE='C' # Do not consider character set in string operations.
local LC_COLLATE='C' # Do not consider character set in pattern matching.
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD - 1]}"
COMPREPLY=()
if [[ "$BASH_VERSINFO" -ge 4 ]]
then # Exponential performance issue on strings greater than about 10k.
local domains="$(defaults domains)"
local candidates=($(compgen -W "${domains//, /$IFS}" | grep -i "^${cur}"))
else
local domains="$(defaults domains | sed -e 's/, /^/g' | tr '^' '\n')"
local candidates=($(compgen -W "${domains}" | grep -i "^${cur}"))
fi
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
if grep -q "^$cur" <<< '-app'
then
COMPREPLY[${#COMPREPLY[@]}]="-app"
elif grep -q "^$cur" <<< '-g'
then
COMPREPLY[${#COMPREPLY[@]}]="-g"
fi
return 0
}
function _defaults()
{
local IFS=$'\n' # Treat only newlines as delimiters in string operations.
local LC_CTYPE='C' # Do not consider character set in string operations.
local LC_COLLATE='C' # Do not consider character set in pattern matching.
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD - 1]}"
COMPREPLY=()
local host_opts cmds cmd domain keys key_index candidates verbs value_types
host_opts=('-currentHost' '-host')
cmds=' delete domains export find help import read read-type rename write '
value_types=('-string' '-data' '-integer' '-float' '-boolean' '-date' '-array' '-array-add' '-dict' '-dict-add')
case $COMP_CWORD in
1)
_defaults_verbs
return "$?"
;;
2)
case $prev in
"-currentHost")
_defaults_verbs
;;
"-host")
_known_hosts -a
;;
*)
if matchpattern "$prev" "${cmds// /|}"
then
# TODO: not correct for verbs: domains, find, help
_defaults_domains
else
return 1 # verb is not recognized
fi
;;
esac
return "$?"
;;
3)
case ${COMP_WORDS[1]} in
"-currentHost")
_defaults_domains
return "$?"
;;
"-host")
_defaults_verbs
return "$?"
;;
esac
;;
4)
case ${COMP_WORDS[1]} in
"-host")
if matchpattern "$prev" "${cmds// /|}"
then
# TODO: not correct for verbs: domains, find, help
_defaults_domains
else
return 1 # verb is not recognized
fi
;;
esac
;;
esac
# Both a domain and command have been specified
case ${COMP_WORDS[1]} in
"-currentHost")
if matchpattern "${COMP_WORDS[2]}" "${cmds// /|}"
then
cmd="${COMP_WORDS[2]}"
domain="${COMP_WORDS[3]}"
key_index=4
if [[ "$domain" == "-app" ]]
then
if [[ $COMP_CWORD -eq 4 ]]
then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[4]}"
key_index=5
fi
fi
;;
"-host")
if matchpattern "${COMP_WORDS[3]}" "${cmds// /|}"
then
cmd="${COMP_WORDS[3]}"
domain="${COMP_WORDS[4]}"
key_index=5
if [[ "$domain" == "-app" ]]
then
if [[ $COMP_CWORD -eq 5 ]]
then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[5]}"
key_index=6
fi
fi
;;
*)
if matchpattern "${COMP_WORDS[1]}" "${cmds// /|}"
then
cmd="${COMP_WORDS[1]}"
domain="${COMP_WORDS[2]}"
key_index=3
if [[ "$domain" == "-app" ]]
then
if [[ $COMP_CWORD -eq 3 ]]
then
# Completing application name. Can't help here, sorry
return 0
fi
domain="-app ${COMP_WORDS[3]}"
key_index=4
fi
fi
;;
esac
keys=($(defaults read "$domain" 2> /dev/null | sed -n -e '/^ [^}) ]/p' | sed -e 's/^ \([^" ]\{1,\}\) = .*$/\1/g' -e 's/^ "\([^"]\{1,\}\)" = .*$/\1/g'))
case $cmd in
read | read-type)
# Complete key
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
;;
write)
if [[ $key_index -eq $COMP_CWORD ]]
then
# Complete key
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
elif [[ $((key_index + 1)) -eq $COMP_CWORD ]]
then
# Complete value type
local cur_type="$(defaults read-type "$domain" "${COMP_WORDS[key_index]}" 2> /dev/null | sed -e 's/^Type is \(.*\)/-\1/' -e's/dictionary/dict/' | grep "^$cur")"
if [[ $cur_type ]]
then
COMPREPLY=("$cur_type")
else
COMPREPLY=($(compgen -W "${value_types[*]}" -- "$cur"))
fi
elif [[ $((key_index + 2)) -eq $COMP_CWORD ]]
then
# Complete value
COMPREPLY=($(defaults read "$domain" "${COMP_WORDS[key_index]}" 2> /dev/null | grep -i "^${cur//\\/\\\\}"))
fi
;;
rename)
if [[ $key_index -eq $COMP_CWORD || $((key_index + 1)) -eq $COMP_CWORD ]]
then
# Complete source and destination keys
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
fi
;;
delete)
if [[ $key_index -eq $COMP_CWORD ]]
then
# Complete key
if candidates=($(compgen -W "${keys[*]:-}" | grep -i "^${cur}"))
then
COMPREPLY=($(printf '%q\n' "${candidates[@]}"))
fi
fi
;;
esac
return 0
}
complete -F _defaults -o default defaults
# This file is licensed under the BSD license, as follows:
#
# Copyright (c) 2006, Playhaus
# Copyright (c) 2021, gaelicWizard.LLC
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the names of the authors nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# This software is provided by the copyright holders and contributors "as is"
# and any express or implied warranties, including, but not limited to, the
# implied warranties of merchantability and fitness for a particular purpose are
# disclaimed. In no event shall the copyright owner or contributors be liable
# for any direct, indirect, incidental, special, exemplary, or consequential
# damages (including, but not limited to, procurement of substitute goods or
# services; loss of use, data, or profits; or business interruption) however
# caused and on any theory of liability, whether in contract, strict liability,
# or tort (including negligence or otherwise) arising in any way out of the use
# of this software, even if advised of the possibility of such damage.

View File

@@ -0,0 +1,40 @@
# EditorConfig is awesome: http://EditorConfig.org
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[**.md]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[.git*]
indent_style = tab
[**.*sh]
indent_style = tab
indent_size = tab
shell_variant = bash
binary_next_line = true # like -bn
switch_case_indent = false # like -ci
space_redirects = true # like -sr
keep_padding = false # like -kp
function_next_line = true # like -fn
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[**.bats]
indent_style = tab
indent_size = tab
shell_variant = bash
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View File

@@ -0,0 +1,184 @@
#!/usr/bin/env bats
load ../test_helper
function local_setup() {
load ../../completion/available/defaults.completion
function _known_hosts() { :; }
function defaults() { echo 'NSGlobalDomain, Bash It'; }
}
function __check_completion() {
# Get the parameters as a single value
COMP_LINE=$*
# Get the parameters as an array
eval set -- "$@"
COMP_WORDS=("$@")
# Index of the cursor in the line
COMP_POINT=${#COMP_LINE}
# Get the last character of the line that was entered
COMP_LAST=$((${COMP_POINT} - 1))
# If the last character was a space...
if [[ ${COMP_LINE:$COMP_LAST} = ' ' ]]; then
# ...then add an empty array item
COMP_WORDS+=('')
fi
# Word index of the last word
COMP_CWORD=$(( ${#COMP_WORDS[@]} - 1 ))
# Run the Bash-it completion function
_defaults
# Return the completion output
echo "${COMPREPLY[@]}"
}
@test "completion defaults: ensure that the _defaults function is available" {
type -a _defaults &> /dev/null
assert_success
}
@test "completion defaults: - show verbs and options" {
run __check_completion 'defaults '
assert_line -n 0 'delete domains export find help import read read-type rename write -currentHost -host'
}
@test "completion defaults: r* - show matching verbs" {
run __check_completion 'defaults r'
assert_line -n 0 'read read-type rename'
}
@test "completion defaults: R* - show matching verbs" {
run __check_completion 'defaults R'
assert_line -n 0 'read read-type rename'
}
@test "completion defaults: -* - show matching flags" {
run __check_completion 'defaults -'
assert_line -n 0 '-currentHost -host'
}
@test "completion defaults: -currentHost - show verbs" {
run __check_completion 'defaults -currentHost '
assert_line -n 0 'delete domains export find help import read read-type rename write'
}
@test "completion defaults: -host - show nothing" {
run __check_completion 'defaults -host '
assert_line -n 0 "$(_known_hosts -a)"
}
@test "completion defaults: -host some_computer_name - show verbs" {
run __check_completion 'defaults -host some_computer_name '
assert_line -n 0 'delete domains export find help import read read-type rename write'
}
@test "completion defaults: read - show all domains" {
run __check_completion 'defaults read '
assert_line -n 0 "NSGlobalDomain Bash\ It -app"
}
@test "completion defaults: read nsg* - show matching domains" {
run __check_completion 'defaults read nsg'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: read NSG* - show matching domains" {
run __check_completion 'defaults read NSG'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: read bash* - show matching domains" {
run __check_completion 'defaults read bash'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: read BASH* - show matching domains" {
run __check_completion 'defaults read BASH'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: read bash* - show matching domains (with spaces)" {
run __check_completion 'defaults read bash\ i'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: read BASH* - show matching domains (with spaces)" {
run __check_completion 'defaults read BASH\ I'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read - show all domains" {
run __check_completion 'defaults -currentHost read '
assert_line -n 0 "NSGlobalDomain Bash\ It -app"
}
@test "completion defaults: -currentHost read nsg* - show matching domains" {
run __check_completion 'defaults -currentHost read nsg'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -currentHost read NSG* - show matching domains" {
run __check_completion 'defaults -currentHost read NSG'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -currentHost read bash* - show matching domains" {
run __check_completion 'defaults -currentHost read bash'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read BASH* - show matching domains" {
run __check_completion 'defaults -currentHost read BASH'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read bash* - show matching domains (with spaces)" {
run __check_completion 'defaults -currentHost read bash\ i'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -currentHost read BASH* - show matching domains (with spaces)" {
run __check_completion 'defaults -currentHost read BASH\ I'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read - show all domains" {
run __check_completion 'defaults -host some.computer.name read '
assert_line -n 0 "NSGlobalDomain Bash\ It -app"
}
@test "completion defaults: -host some.computer.name read nsg* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read nsg'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -host some.computer.name read NSG* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read NSG'
assert_line -n 0 "NSGlobalDomain"
}
@test "completion defaults: -host some.computer.name read bash* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read bash'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read BASH* - show matching domains" {
run __check_completion 'defaults -host some.computer.name read BASH'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read bash* - show matching domains (with spaces)" {
run __check_completion 'defaults -host some.computer.name read bash\ i'
assert_line -n 0 "Bash\ It"
}
@test "completion defaults: -host some.computer.name read BASH* - show matching domains (with spaces)" {
run __check_completion 'defaults -host some.computer.name read BASH\ I'
assert_line -n 0 "Bash\ It"
}

View File

@@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2017 Ryan Caloras and contributors (see https://github.com/rcaloras/bash-preexec)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,107 @@
[![Build Status](https://travis-ci.org/rcaloras/bash-preexec.svg?branch=master)](https://travis-ci.org/rcaloras/bash-preexec)
[![GitHub version](https://badge.fury.io/gh/rcaloras%2Fbash-preexec.svg)](https://badge.fury.io/gh/rcaloras%2Fbash-preexec)
Bash-Preexec
============
**preexec** and **precmd** hook functions for Bash in the style of Zsh. They aim to emulate the behavior [as described for Zsh](http://zsh.sourceforge.net/Doc/Release/Functions.html#Hook-Functions).
<a href="https://bashhub.com" target="_blank"><img src="https://bashhub.com/assets/images/bashhub-logo.png" alt="Bashhub Logo" width="200"></a>
This project is currently being used in production by [Bashhub](https://github.com/rcaloras/bashhub-client) and [iTerm2](https://github.com/gnachman/iTerm2). Hype!
## Quick Start
```bash
# Pull down our file from GitHub and write it to our home directory as a hidden file.
curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh
# Source our file to bring it into our environment
source ~/.bash-preexec.sh
# Define a couple functions.
preexec() { echo "just typed $1"; }
precmd() { echo "printing the prompt"; }
```
## Install
You'll want to pull down the file and add it to your bash profile/configuration (i.e ~/.bashrc, ~/.profile, ~/.bash_profile, etc). **It must be the last thing imported in your bash profile.**
```bash
# Pull down our file from GitHub and write it to our home directory as a hidden file.
curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh -o ~/.bash-preexec.sh
# Source our file at the end of our bash profile (e.g. ~/.bashrc, ~/.profile, or ~/.bash_profile)
echo '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' >> ~/.bashrc
```
## Usage
Two functions **preexec** and **precmd** can now be defined and they'll be automatically invoked by bash-preexec if they exist.
* `preexec` Executed just after a command has been read and is about to be executed. The string that the user typed is passed as the first argument.
* `precmd` Executed just before each prompt. Equivalent to PROMPT_COMMAND, but more flexible and resilient.
```bash
source ~/.bash-preexec.sh
preexec() { echo "just typed $1"; }
precmd() { echo "printing the prompt"; }
```
Should output something like:
```
elementz@Kashmir:~/git/bash-preexec (master)$ ls
just typed ls
bash-preexec.sh README.md test
printing the prompt
```
#### Function Arrays
You can also define functions to be invoked by appending them to two different arrays. This is great if you want to have many functions invoked for either hook. Both preexec and precmd functions are added to these by default and don't need to be added manually.
* `$preexec_functions` Array of functions invoked by preexec.
* `$precmd_functions` Array of functions invoked by precmd.
#### preexec
```bash
# Define some function to use preexec
preexec_hello_world() { echo "You just entered $1"; }
# Add it to the array of functions to be invoked each time.
preexec_functions+=(preexec_hello_world)
```
#### precmd
```bash
precmd_hello_world() { echo "This is invoked before the prompt is displayed"; }
precmd_functions+=(precmd_hello_world)
```
You can also define multiple functions to be invoked like so.
```bash
precmd_hello_one() { echo "This is invoked on precmd first"; }
precmd_hello_two() { echo "This is invoked on precmd second"; }
precmd_functions+=(precmd_hello_one)
precmd_functions+=(precmd_hello_two)
```
You can check the functions set for each by echoing its contents.
```bash
echo ${preexec_functions[@]}
echo ${precmd_functions[@]}
```
## Subshells
bash-preexec does not support invoking preexec() for subshells by default. It must be enabled by setting
`__bp_enable_subshells`.
```bash
# Enable experimental subshell support
export __bp_enable_subshells="true"
```
This is disabled by default due to buggy situations related to to `functrace` and Bash's `DEBUG trap`. See [Issue #25](https://github.com/rcaloras/bash-preexec/issues/25)
## Tests
You can run tests using [Bats](https://github.com/bats-core/bats-core).
```bash
bats test
```
Should output something like:
```
elementz@Kashmir:~/git/bash-preexec(master)$ bats test
✓ No functions defined for preexec should simply return
✓ precmd should execute a function once
✓ preexec should execute a function with the last command in our history
✓ preexec should execute multiple functions in the order added to their arrays
✓ preecmd should execute multiple functions in the order added to their arrays
```

View File

@@ -0,0 +1,351 @@
# bash-preexec.sh -- Bash support for ZSH-like 'preexec' and 'precmd' functions.
# https://github.com/rcaloras/bash-preexec
#
#
# 'preexec' functions are executed before each interactive command is
# executed, with the interactive command as its argument. The 'precmd'
# function is executed before each prompt is displayed.
#
# Author: Ryan Caloras (ryan@bashhub.com)
# Forked from Original Author: Glyph Lefkowitz
#
# V0.4.1
#
# General Usage:
#
# 1. Source this file at the end of your bash profile so as not to interfere
# with anything else that's using PROMPT_COMMAND.
#
# 2. Add any precmd or preexec functions by appending them to their arrays:
# e.g.
# precmd_functions+=(my_precmd_function)
# precmd_functions+=(some_other_precmd_function)
#
# preexec_functions+=(my_preexec_function)
#
# 3. Consider changing anything using the DEBUG trap or PROMPT_COMMAND
# to use preexec and precmd instead. Preexisting usages will be
# preserved, but doing so manually may be less surprising.
#
# Note: This module requires two Bash features which you must not otherwise be
# using: the "DEBUG" trap, and the "PROMPT_COMMAND" variable. If you override
# either of these after bash-preexec has been installed it will most likely break.
# Make sure this is bash that's running and return otherwise.
if [[ -z "${BASH_VERSION:-}" ]]; then
return 1;
fi
# Avoid duplicate inclusion
if [[ -n "${bash_preexec_imported:-}" ]]; then
return 0
fi
bash_preexec_imported="defined"
# WARNING: This variable is no longer used and should not be relied upon.
# Use ${bash_preexec_imported} instead.
__bp_imported="${bash_preexec_imported}"
# Should be available to each precmd and preexec
# functions, should they want it. $? and $_ are available as $? and $_, but
# $PIPESTATUS is available only in a copy, $BP_PIPESTATUS.
# TODO: Figure out how to restore PIPESTATUS before each precmd or preexec
# function.
__bp_last_ret_value="$?"
BP_PIPESTATUS=("${PIPESTATUS[@]}")
__bp_last_argument_prev_command="$_"
__bp_inside_precmd=0
__bp_inside_preexec=0
# Initial PROMPT_COMMAND string that is removed from PROMPT_COMMAND post __bp_install
__bp_install_string=$'__bp_trap_string="$(trap -p DEBUG)"\ntrap - DEBUG\n__bp_install'
# Fails if any of the given variables are readonly
# Reference https://stackoverflow.com/a/4441178
__bp_require_not_readonly() {
local var
for var; do
if ! ( unset "$var" 2> /dev/null ); then
echo "bash-preexec requires write access to ${var}" >&2
return 1
fi
done
}
# Remove ignorespace and or replace ignoreboth from HISTCONTROL
# so we can accurately invoke preexec with a command from our
# history even if it starts with a space.
__bp_adjust_histcontrol() {
local histcontrol
histcontrol="${HISTCONTROL:-}"
histcontrol="${histcontrol//ignorespace}"
# Replace ignoreboth with ignoredups
if [[ "$histcontrol" == *"ignoreboth"* ]]; then
histcontrol="ignoredups:${histcontrol//ignoreboth}"
fi;
export HISTCONTROL="$histcontrol"
}
# This variable describes whether we are currently in "interactive mode";
# i.e. whether this shell has just executed a prompt and is waiting for user
# input. It documents whether the current command invoked by the trace hook is
# run interactively by the user; it's set immediately after the prompt hook,
# and unset as soon as the trace hook is run.
__bp_preexec_interactive_mode=""
# These arrays are used to add functions to be run before, or after, prompts.
declare -a precmd_functions
declare -a preexec_functions
# Trims leading and trailing whitespace from $2 and writes it to the variable
# name passed as $1
__bp_trim_whitespace() {
local var=${1:?} text=${2:-}
text="${text#"${text%%[![:space:]]*}"}" # remove leading whitespace characters
text="${text%"${text##*[![:space:]]}"}" # remove trailing whitespace characters
printf -v "$var" '%s' "$text"
}
# Trims whitespace and removes any leading or trailing semicolons from $2 and
# writes the resulting string to the variable name passed as $1. Used for
# manipulating substrings in PROMPT_COMMAND
__bp_sanitize_string() {
local var=${1:?} text=${2:-} sanitized
__bp_trim_whitespace sanitized "$text"
sanitized=${sanitized%;}
sanitized=${sanitized#;}
__bp_trim_whitespace sanitized "$sanitized"
printf -v "$var" '%s' "$sanitized"
}
# This function is installed as part of the PROMPT_COMMAND;
# It sets a variable to indicate that the prompt was just displayed,
# to allow the DEBUG trap to know that the next command is likely interactive.
__bp_interactive_mode() {
__bp_preexec_interactive_mode="on";
}
# This function is installed as part of the PROMPT_COMMAND.
# It will invoke any functions defined in the precmd_functions array.
__bp_precmd_invoke_cmd() {
# Save the returned value from our last command, and from each process in
# its pipeline. Note: this MUST be the first thing done in this function.
__bp_last_ret_value="$?" BP_PIPESTATUS=("${PIPESTATUS[@]}")
# Don't invoke precmds if we are inside an execution of an "original
# prompt command" by another precmd execution loop. This avoids infinite
# recursion.
if (( __bp_inside_precmd > 0 )); then
return
fi
local __bp_inside_precmd=1
# Invoke every function defined in our function array.
local precmd_function
for precmd_function in "${precmd_functions[@]}"; do
# Only execute this function if it actually exists.
# Test existence of functions with: declare -[Ff]
if type -t "$precmd_function" 1>/dev/null; then
__bp_set_ret_value "$__bp_last_ret_value" "$__bp_last_argument_prev_command"
# Quote our function invocation to prevent issues with IFS
"$precmd_function"
fi
done
}
# Sets a return value in $?. We may want to get access to the $? variable in our
# precmd functions. This is available for instance in zsh. We can simulate it in bash
# by setting the value here.
__bp_set_ret_value() {
return ${1:-}
}
__bp_in_prompt_command() {
local prompt_command_array
IFS=$'\n;' read -rd '' -a prompt_command_array <<< "${PROMPT_COMMAND:-}"
local trimmed_arg
__bp_trim_whitespace trimmed_arg "${1:-}"
local command trimmed_command
for command in "${prompt_command_array[@]:-}"; do
__bp_trim_whitespace trimmed_command "$command"
if [[ "$trimmed_command" == "$trimmed_arg" ]]; then
return 0
fi
done
return 1
}
# This function is installed as the DEBUG trap. It is invoked before each
# interactive prompt display. Its purpose is to inspect the current
# environment to attempt to detect if the current command is being invoked
# interactively, and invoke 'preexec' if so.
__bp_preexec_invoke_exec() {
# Save the contents of $_ so that it can be restored later on.
# https://stackoverflow.com/questions/40944532/bash-preserve-in-a-debug-trap#40944702
__bp_last_argument_prev_command="${1:-}"
# Don't invoke preexecs if we are inside of another preexec.
if (( __bp_inside_preexec > 0 )); then
return
fi
local __bp_inside_preexec=1
# Checks if the file descriptor is not standard out (i.e. '1')
# __bp_delay_install checks if we're in test. Needed for bats to run.
# Prevents preexec from being invoked for functions in PS1
if [[ ! -t 1 && -z "${__bp_delay_install:-}" ]]; then
return
fi
if [[ -n "${COMP_LINE:-}" ]]; then
# We're in the middle of a completer. This obviously can't be
# an interactively issued command.
return
fi
if [[ -z "${__bp_preexec_interactive_mode:-}" ]]; then
# We're doing something related to displaying the prompt. Let the
# prompt set the title instead of me.
return
else
# If we're in a subshell, then the prompt won't be re-displayed to put
# us back into interactive mode, so let's not set the variable back.
# In other words, if you have a subshell like
# (sleep 1; sleep 2)
# You want to see the 'sleep 2' as a set_command_title as well.
if [[ 0 -eq "${BASH_SUBSHELL:-}" ]]; then
__bp_preexec_interactive_mode=""
fi
fi
if __bp_in_prompt_command "${BASH_COMMAND:-}"; then
# If we're executing something inside our prompt_command then we don't
# want to call preexec. Bash prior to 3.1 can't detect this at all :/
__bp_preexec_interactive_mode=""
return
fi
local this_command
this_command=$(
export LC_ALL=C
HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //'
)
# Sanity check to make sure we have something to invoke our function with.
if [[ -z "$this_command" ]]; then
return
fi
# Invoke every function defined in our function array.
local preexec_function
local preexec_function_ret_value
local preexec_ret_value=0
for preexec_function in "${preexec_functions[@]:-}"; do
# Only execute each function if it actually exists.
# Test existence of function with: declare -[fF]
if type -t "$preexec_function" 1>/dev/null; then
__bp_set_ret_value ${__bp_last_ret_value:-}
# Quote our function invocation to prevent issues with IFS
"$preexec_function" "$this_command"
preexec_function_ret_value="$?"
if [[ "$preexec_function_ret_value" != 0 ]]; then
preexec_ret_value="$preexec_function_ret_value"
fi
fi
done
# Restore the last argument of the last executed command, and set the return
# value of the DEBUG trap to be the return code of the last preexec function
# to return an error.
# If `extdebug` is enabled a non-zero return value from any preexec function
# will cause the user's command not to execute.
# Run `shopt -s extdebug` to enable
__bp_set_ret_value "$preexec_ret_value" "$__bp_last_argument_prev_command"
}
__bp_install() {
# Exit if we already have this installed.
if [[ "${PROMPT_COMMAND:-}" == *"__bp_precmd_invoke_cmd"* ]]; then
return 1;
fi
trap '__bp_preexec_invoke_exec "$_"' DEBUG
# Preserve any prior DEBUG trap as a preexec function
local prior_trap=$(sed "s/[^']*'\(.*\)'[^']*/\1/" <<<"${__bp_trap_string:-}")
unset __bp_trap_string
if [[ -n "$prior_trap" ]]; then
eval '__bp_original_debug_trap() {
'"$prior_trap"'
}'
preexec_functions+=(__bp_original_debug_trap)
fi
# Adjust our HISTCONTROL Variable if needed.
__bp_adjust_histcontrol
# Issue #25. Setting debug trap for subshells causes sessions to exit for
# backgrounded subshell commands (e.g. (pwd)& ). Believe this is a bug in Bash.
#
# Disabling this by default. It can be enabled by setting this variable.
if [[ -n "${__bp_enable_subshells:-}" ]]; then
# Set so debug trap will work be invoked in subshells.
set -o functrace > /dev/null 2>&1
shopt -s extdebug > /dev/null 2>&1
fi;
local existing_prompt_command
# Remove setting our trap install string and sanitize the existing prompt command string
existing_prompt_command="${PROMPT_COMMAND:-}"
existing_prompt_command="${existing_prompt_command//$__bp_install_string[;$'\n']}" # Edge case of appending to PROMPT_COMMAND
existing_prompt_command="${existing_prompt_command//$__bp_install_string}"
__bp_sanitize_string existing_prompt_command "$existing_prompt_command"
# Install our hooks in PROMPT_COMMAND to allow our trap to know when we've
# actually entered something.
PROMPT_COMMAND=$'__bp_precmd_invoke_cmd\n'
if [[ -n "$existing_prompt_command" ]]; then
PROMPT_COMMAND+=${existing_prompt_command}$'\n'
fi;
PROMPT_COMMAND+='__bp_interactive_mode'
# Add two functions to our arrays for convenience
# of definition.
precmd_functions+=(precmd)
preexec_functions+=(preexec)
# Invoke our two functions manually that were added to $PROMPT_COMMAND
__bp_precmd_invoke_cmd
__bp_interactive_mode
}
# Sets an installation string as part of our PROMPT_COMMAND to install
# after our session has started. This allows bash-preexec to be included
# at any point in our bash profile.
__bp_install_after_session_init() {
# bash-preexec needs to modify these variables in order to work correctly
# if it can't, just stop the installation
__bp_require_not_readonly PROMPT_COMMAND HISTCONTROL HISTTIMEFORMAT || return
local sanitized_prompt_command
__bp_sanitize_string sanitized_prompt_command "${PROMPT_COMMAND:-}"
if [[ -n "$sanitized_prompt_command" ]]; then
PROMPT_COMMAND=${sanitized_prompt_command}$'\n'
fi;
PROMPT_COMMAND+=${__bp_install_string}
}
# Run our install so long as we're not delaying it.
if [[ -z "${__bp_delay_install:-}" ]]; then
__bp_install_after_session_init
fi;

View File

@@ -0,0 +1,20 @@
language: bash
before_install:
# To install bats and test our shell/bash functions
- git clone -b "v1.1.0" "https://github.com/bats-core/bats-core.git"
- sudo ./bats-core/install.sh /usr/local
- rm -rf ./bats-core
- sudo apt-get install -qq zsh
# For bats functional tests
env:
- functional_test="true"
# command to run tests
script:
- /usr/local/bin/bats test
notifications:
email:
on_success: never

View File

@@ -0,0 +1,22 @@
Testing `bash-preexec`
======================
**Note on test conditions**
When writing test conditions, use `[ ... ]` instead of `[[ ... ]]` since the
former are supported by Bats on Bash versions before 4.1. In particular, macOS
uses Bash 3.2, and `[[ ... ]]` tests always pass on macOS.
In some cases, you may want to use a feature unique to `[[ ... ]]` such as
pattern matching (`[[ $name = a* ]]`) or regular expressions (`[[ $(date) =~
^Fri\ ...\ 13 ]]`). In those cases, use the following pattern to replace “bare”
`[[ ... ]]`.
```
[[ ... ]] || return 1
```
References:
* [Differences between `[` and `[[`](http://mywiki.wooledge.org/BashFAQ/031)
* [Problems with `[[` in Bats](https://github.com/sstephenson/bats/issues/49)
* [Using `|| return 1` instead of `|| false`](https://github.com/bats-core/bats-core/commit/e5695a673faad4d4d33446ed5c99d70dbfa6d8be)

View File

@@ -0,0 +1,364 @@
#!/usr/bin/env bats
setup() {
PROMPT_COMMAND='' # in case the invoking shell has set this
history -s fake command # preexec requires there be some history
set -o nounset # in case the user has this set
__bp_delay_install="true"
source "${BATS_TEST_DIRNAME}/../bash-preexec.sh"
}
bp_install() {
__bp_install_after_session_init
eval "$PROMPT_COMMAND"
}
test_echo() {
echo "test echo"
}
test_preexec_echo() {
printf "%s\n" "$1"
}
@test "__bp_install_after_session_init should exit with 1 if we're not using bash" {
unset BASH_VERSION
run '__bp_install_after_session_init'
[ $status -eq 1 ]
[ -z "$output" ]
}
@test "__bp_install should exit if it's already installed" {
bp_install
run '__bp_install'
[ $status -eq 1 ]
[ -z "$output" ]
}
@test "__bp_install should remove trap logic and itself from PROMPT_COMMAND" {
__bp_install_after_session_init
[[ "$PROMPT_COMMAND" == *"trap - DEBUG"* ]] || return 1
[[ "$PROMPT_COMMAND" == *"__bp_install"* ]] || return 1
eval "$PROMPT_COMMAND"
[[ "$PROMPT_COMMAND" != *"trap DEBUG"* ]] || return 1
[[ "$PROMPT_COMMAND" != *"__bp_install"* ]] || return 1
}
@test "__bp_install should preserve an existing DEBUG trap" {
trap_invoked_count=0
foo() { (( trap_invoked_count += 1 )); }
# note setting this causes BATS to mis-report the failure line when this test fails
trap foo DEBUG
[ "$(trap -p DEBUG | cut -d' ' -f3)" == "'foo'" ]
bp_install
trap_count_snapshot=$trap_invoked_count
[ "$(trap -p DEBUG | cut -d' ' -f3)" == "'__bp_preexec_invoke_exec" ]
[[ "${preexec_functions[*]}" == *"__bp_original_debug_trap"* ]] || return 1
__bp_interactive_mode # triggers the DEBUG trap
# ensure the trap count is still being incremented after the trap's been overwritten
(( trap_count_snapshot < trap_invoked_count ))
}
@test "__bp_sanitize_string should remove semicolons and trim space" {
__bp_sanitize_string output " true1; "$'\n'
[ "$output" == "true1" ]
__bp_sanitize_string output " ; true2; "
[ "$output" == "true2" ]
__bp_sanitize_string output $'\n'" ; true3; "
[ "$output" == "true3" ]
}
@test "Appending to PROMPT_COMMAND should work after bp_install" {
bp_install
PROMPT_COMMAND="$PROMPT_COMMAND; true"
eval "$PROMPT_COMMAND"
}
@test "Appending or prepending to PROMPT_COMMAND should work after bp_install_after_session_init" {
__bp_install_after_session_init
nl=$'\n'
PROMPT_COMMAND="$PROMPT_COMMAND; true"
PROMPT_COMMAND="$PROMPT_COMMAND $nl true"
PROMPT_COMMAND="$PROMPT_COMMAND; true"
PROMPT_COMMAND="true; $PROMPT_COMMAND"
PROMPT_COMMAND="true; $PROMPT_COMMAND"
PROMPT_COMMAND="true; $PROMPT_COMMAND"
PROMPT_COMMAND="true $nl $PROMPT_COMMAND"
eval "$PROMPT_COMMAND"
}
# Case where a user is appending or prepending to PROMPT_COMMAND.
# This can happen after 'source bash-preexec.sh' e.g.
# source bash-preexec.sh; PROMPT_COMMAND="$PROMPT_COMMAND; other_prompt_command_hook"
@test "Adding to PROMPT_COMMAND before and after initiating install" {
PROMPT_COMMAND="echo before"
PROMPT_COMMAND="$PROMPT_COMMAND; echo before2"
__bp_install_after_session_init
PROMPT_COMMAND="$PROMPT_COMMAND"$'\n echo after'
PROMPT_COMMAND="echo after2; $PROMPT_COMMAND;"
eval "$PROMPT_COMMAND"
expected_result=$'__bp_precmd_invoke_cmd\necho after2; echo before; echo before2\n echo after\n__bp_interactive_mode'
[ "$PROMPT_COMMAND" == "$expected_result" ]
}
@test "Adding to PROMPT_COMMAND after with semicolon" {
PROMPT_COMMAND="echo before"
__bp_install_after_session_init
PROMPT_COMMAND="$PROMPT_COMMAND; echo after"
eval "$PROMPT_COMMAND"
expected_result=$'__bp_precmd_invoke_cmd\necho before\n echo after\n__bp_interactive_mode'
[ "$PROMPT_COMMAND" == "$expected_result" ]
}
@test "during install PROMPT_COMMAND and precmd functions should be executed each once" {
PROMPT_COMMAND="echo before"
PROMPT_COMMAND="$PROMPT_COMMAND; echo before2"
__bp_install_after_session_init
PROMPT_COMMAND="$PROMPT_COMMAND; echo after"
PROMPT_COMMAND="echo after2; $PROMPT_COMMAND;"
precmd() { echo "inside precmd"; }
run eval "$PROMPT_COMMAND"
[ "${lines[0]}" == "after2" ]
[ "${lines[1]}" == "before" ]
[ "${lines[2]}" == "before2" ]
[ "${lines[3]}" == "inside precmd" ]
[ "${lines[4]}" == "after" ]
[ "${#lines[@]}" == '5' ]
}
@test "No functions defined for preexec should simply return" {
__bp_interactive_mode
run '__bp_preexec_invoke_exec' 'true'
[ $status -eq 0 ]
[ -z "$output" ]
}
@test "precmd should execute a function once" {
precmd_functions+=(test_echo)
run '__bp_precmd_invoke_cmd'
[ $status -eq 0 ]
[ "$output" == "test echo" ]
}
@test "precmd should set \$? to be the previous exit code" {
echo_exit_code() {
echo "$?"
}
return_exit_code() {
return $1
}
# Helper function is necessary because Bats' run doesn't preserve $?
set_exit_code_and_run_precmd() {
return_exit_code 251
__bp_precmd_invoke_cmd
}
precmd_functions+=(echo_exit_code)
run 'set_exit_code_and_run_precmd'
[ $status -eq 0 ]
[ "$output" == "251" ]
}
@test "precmd should set \$BP_PIPESTATUS to the previous \$PIPESTATUS" {
echo_pipestatus() {
echo "${BP_PIPESTATUS[*]}"
}
# Helper function is necessary because Bats' run doesn't preserve $PIPESTATUS
set_pipestatus_and_run_precmd() {
false | true
__bp_precmd_invoke_cmd
}
precmd_functions+=(echo_pipestatus)
run 'set_pipestatus_and_run_precmd'
[ $status -eq 0 ]
[ "$output" == "1 0" ]
}
@test "precmd should set \$_ to be the previous last arg" {
echo_last_arg() {
echo "$_"
}
precmd_functions+=(echo_last_arg)
bats_trap=$(trap -p DEBUG)
trap DEBUG # remove the Bats stack-trace trap so $_ doesn't get overwritten
: "last-arg"
__bp_preexec_invoke_exec "$_"
eval "$bats_trap" # Restore trap
run '__bp_precmd_invoke_cmd'
[ $status -eq 0 ]
[ "$output" == "last-arg" ]
}
@test "preexec should execute a function with the last command in our history" {
preexec_functions+=(test_preexec_echo)
__bp_interactive_mode
git_command="git commit -a -m 'committing some stuff'"
history -s $git_command
run '__bp_preexec_invoke_exec'
[ $status -eq 0 ]
[ "$output" == "$git_command" ]
}
@test "preexec should execute multiple functions in the order added to their arrays" {
fun_1() { echo "$1 one"; }
fun_2() { echo "$1 two"; }
preexec_functions+=(fun_1)
preexec_functions+=(fun_2)
__bp_interactive_mode
run '__bp_preexec_invoke_exec'
[ $status -eq 0 ]
[ "${#lines[@]}" == '2' ]
[ "${lines[0]}" == "fake command one" ]
[ "${lines[1]}" == "fake command two" ]
}
@test "preecmd should execute multiple functions in the order added to their arrays" {
fun_1() { echo "one"; }
fun_2() { echo "two"; }
precmd_functions+=(fun_1)
precmd_functions+=(fun_2)
run '__bp_precmd_invoke_cmd'
[ $status -eq 0 ]
[ "${#lines[@]}" == '2' ]
[ "${lines[0]}" == "one" ]
[ "${lines[1]}" == "two" ]
}
@test "preexec should execute a function with IFS defined to local scope" {
IFS=_
name_with_underscores_1() { parts=(1_2); echo $parts; }
preexec_functions+=(name_with_underscores_1)
__bp_interactive_mode
run '__bp_preexec_invoke_exec'
[ $status -eq 0 ]
[ "$output" == "1 2" ]
}
@test "precmd should execute a function with IFS defined to local scope" {
IFS=_
name_with_underscores_2() { parts=(2_2); echo $parts; }
precmd_functions+=(name_with_underscores_2)
run '__bp_precmd_invoke_cmd'
[ $status -eq 0 ]
[ "$output" == "2 2" ]
}
@test "preexec should set \$? to be the exit code of preexec_functions" {
return_nonzero() {
return 1
}
preexec_functions+=(return_nonzero)
__bp_interactive_mode
run '__bp_preexec_invoke_exec'
[ $status -eq 1 ]
}
@test "in_prompt_command should detect if a command is part of PROMPT_COMMAND" {
PROMPT_COMMAND=$'precmd_invoke_cmd\n something; echo yo\n __bp_interactive_mode'
run '__bp_in_prompt_command' "something"
[ $status -eq 0 ]
run '__bp_in_prompt_command' "something_else"
[ $status -eq 1 ]
# Should trim commands and arguments here.
PROMPT_COMMAND=" precmd_invoke_cmd ; something ; some_stuff_here;"
run '__bp_in_prompt_command' " precmd_invoke_cmd "
[ $status -eq 0 ]
PROMPT_COMMAND=" precmd_invoke_cmd ; something ; some_stuff_here;"
run '__bp_in_prompt_command' " not_found"
[ $status -eq 1 ]
}
@test "__bp_adjust_histcontrol should remove ignorespace and ignoreboth" {
# Should remove ignorespace
HISTCONTROL="ignorespace:ignoredups:*"
__bp_adjust_histcontrol
[ "$HISTCONTROL" == ":ignoredups:*" ]
# Should remove ignoreboth and replace it with ignoredups
HISTCONTROL="ignoreboth"
__bp_adjust_histcontrol
[ "$HISTCONTROL" == "ignoredups:" ]
# Handle a few inputs
HISTCONTROL="ignoreboth:ignorespace:some_thing_else"
__bp_adjust_histcontrol
echo "$HISTCONTROL"
[ "$HISTCONTROL" == "ignoredups:::some_thing_else" ]
}
@test "preexec should respect HISTTIMEFORMAT" {
preexec_functions+=(test_preexec_echo)
__bp_interactive_mode
git_command="git commit -a -m 'committing some stuff'"
HISTTIMEFORMAT='%F %T '
history -s $git_command
run '__bp_preexec_invoke_exec'
[ $status -eq 0 ]
[ "$output" == "$git_command" ]
}
@test "preexec should not strip whitespace from commands" {
preexec_functions+=(test_preexec_echo)
__bp_interactive_mode
history -s " this command has whitespace "
run '__bp_preexec_invoke_exec'
[ $status -eq 0 ]
[ "$output" == " this command has whitespace " ]
}
@test "preexec should preserve multi-line strings in commands" {
preexec_functions+=(test_preexec_echo)
__bp_interactive_mode
history -s "this 'command contains
a multiline string'"
run '__bp_preexec_invoke_exec'
[ $status -eq 0 ]
[ "$output" == "this 'command contains
a multiline string'" ]
}
@test "preexec should work on options to 'echo' commands" {
preexec_functions+=(test_preexec_echo)
__bp_interactive_mode
history -s -- '-n'
run '__bp_preexec_invoke_exec'
[ $status -eq 0 ]
[ "$output" == '-n' ]
}

View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bats
@test "should not import if it's already defined" {
__bp_imported="defined"
source "${BATS_TEST_DIRNAME}/../bash-preexec.sh"
[ -z $(type -t __bp_preexec_and_precmd_install) ]
}
@test "should import if not defined" {
unset __bp_imported
source "${BATS_TEST_DIRNAME}/../bash-preexec.sh"
[ -n $(type -t __bp_install) ]
}
@test "bp should stop installation if HISTTIMEFORMAT is readonly" {
readonly HISTTIMEFORMAT
run source "${BATS_TEST_DIRNAME}/../bash-preexec.sh"
[ $status -ne 0 ]
[[ "$output" =~ "HISTTIMEFORMAT" ]] || return 1
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Raphael Parree
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,37 @@
jboss-bash-completion
=====================
JBoss Bash Completion for JBoss 5 and 7 (EAP 6)
Overview
--------
Completion for the `run.sh` (JBoss5) and `standalone.sh`/`domain.sh`
Some of the options available in jboss7:
* `--admin-only` `-h` `-help` `-version` `-V` `-v`
* `-Djboss.home.dir`
* `--server-config` (options the xml files in the configuration directory relative to -Djboss.server.base.dir)
* `-b` `-bmanagement` `-bunsecure` `-bpublic` `-Djboss.domain.master.address` `-Djboss.bind.address.*` (options: your local IP addresses and 0.0.0.0)
* `-Djboss.socket.binding.port-offset` (options: 100 200 300 400 10000 20000 30000 40000)
* `-u` (options 239.255.0.1 239.255.0.2 239.255.0.3)
* `-P` -Djboss.node.name
Install
-------
Make sure you have installed bash_completion 1.3 (or higher):
Debian/Ubuntu: `apt-get install bash-completion`
RHEL/CentOS: `yum install bash-completion`
Copy the file(s) to your `/etc/bash_completion.d` folder:
`sudo cp jboss* /etc/bash_completion.d`

View File

@@ -0,0 +1,95 @@
# Completions for JBoss Application Server 5
# VERSION: 1.3
# DATE: 2012-06-21
# rparree-at-edc4it-dot-com
_serverProfiles5(){
# from http://unix.stackexchange.com/questions/34238/complete-files-from-a-different-directory-in-bash
if [ -d "../server" ]
then
IFS=$'\n' tmp=( $(compgen -W "$(ls "../server")" -- "$cur" ))
COMPREPLY=( "${tmp[@]// /\ }" )
unset IFS
else
COMPREPLY=( $(compgen -W "default standard all web minimal production" -- ${cur}) )
fi
}
_bindingAddress5(){
# from /etc/bash_completion.d/ssh
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \
"0.0.0.0 $( PATH="$PATH:/sbin" ifconfig -a | \
sed -ne 's/.*addr:\([^[:space:]]*\).*/\1/p' \
-ne 's/.*inet[[:space:]]\{1,\}\([^[:space:]]*\).*/\1/p' )" \
-- "$cur" ) )
}
_jboss5()
{
local cur prev words cword
COMPREPLY=()
_get_comp_words_by_ref -n = cur prev words cword
case $cur in
-Djboss.service.binding.set=*)
cur=${cur#*=}
#static list of common bindings sets
local bindings="ports-01 ports-02 ports-03 ports-04"
COMPREPLY=( $(compgen -W "${bindings}" -- ${cur}) )
return 0
;;
-Djboss.default.jgroups.stack=*)
cur=${cur#*=}
#static list of standard JGroups stacks
local stacks="udp udp-async udp-sync tcp tcp-sync"
COMPREPLY=( $(compgen -W "${stacks}" -- ${cur}) )
return 0
;;
-Dorg.jboss.ejb3.remoting.IsLocalInterceptor.passByRef=*|-Dcom.sun.management.jmxremote.authenticate=*|-Dcom.sun.management.jmxremote.ssl=*)
cur=${cur#*=}
local booleans="true false"
COMPREPLY=( $(compgen -W "${booleans}" -- ${cur}) )
return 0
;;
esac
case $prev in
-u)
# a few from RFC 2365 IPv4 Local Scope ()
local addresses="239.255.0.1 239.255.0.2 239.255.0.3"
COMPREPLY=( $(compgen -W "${addresses}" -- ${cur}) )
return 0
;;
-l)
local loggers="log4j jdk"
COMPREPLY=( $(compgen -W "${loggers}" -- ${cur}) )
return 0
;;
-b)
_bindingAddress5
return 0
;;
-c)
_serverProfiles5
return 0
;;
*)
;;
esac
COMPREPLY=( $( compgen -W ' -u -c -m - -b -g -l -d -p -n -B -L -C -P -v -help -Djboss.platform.mbeanserver' -- "$cur" ) \
$( compgen -W '-Djboss.Domain -Djboss.modcluster.proxyList -Djboss.service.binding.set -Djboss.jvmRoute -Djboss.messaging.ServerPeerID -Djboss.default.jgroups.stack -Dorg.jboss.ejb3.remoting.IsLocalInterceptor.passByRef -Djboss.platform.mbeanserver -Dcom.sun.management.jmxremote.port -Dcom.sun.management.jmxremote.ssl' \
-S '=' -- "$cur" ) )
return 0
}
complete -o nospace -F _jboss5 run.sh

View File

@@ -0,0 +1,141 @@
# Completions for JBoss Application Server 7 (EAP 6)
# VERSION: 0.6
# DATE: 2012-10-30
# rparree-at-edc4it-dot-com
_serverProfiles(){
if [[ $COMP_WORDS == *standalone.sh* ]]
then
serverdir="../standalone/configuration/"
else
# assume is domain.sh
serverdir="../domain/configuration/"
fi
for i in ${!COMP_WORDS[*]}
do
if [[ "${COMP_WORDS[i]}" == "-Djboss.server.base.dir" || "${COMP_WORDS[i]}" == "-Djboss.domain.base.dir" ]]; then
serverdir="${COMP_WORDS[i+2]}/configuration"
fi
done
if [ -d "${serverdir}" ]
then
IFS=$'\n' tmp="$(ls "${serverdir}" | grep xml)"
local fls="${tmp[@]// /\ }"
unset IFS
COMPREPLY=( $(compgen -W "${fls} initial boot last v" -- "$cur" ))
fi
}
_bindingAddress(){
# from /etc/bash_completion.d/ssh
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \
"0.0.0.0 $( PATH="$PATH:/sbin" ifconfig -a | \
sed -ne 's/.*addr:\([^[:space:]]*\).*/\1/p' \
-ne 's/.*inet[[:space:]]\{1,\}\([^[:space:]]*\).*/\1/p' )" \
-- "$cur" ) )
}
_jboss(){
local cur prev words cword
COMPREPLY=()
_get_comp_words_by_ref -n = cur prev words cword
case $cur in
-Djboss.socket.binding.port-offset=*)
cur=${cur#*=}
#static list of common bindings sets
local bindings="100 200 300 400 10000 20000 30000 40000"
COMPREPLY=( $(compgen -W "${bindings}" -- ${cur}) )
return 0
;;
-Djboss.default.jgroups.stack=*)
cur=${cur#*=}
#static list of standard JGroups stacks
local stacks="udp udp-async udp-sync tcp tcp-sync"
COMPREPLY=( $(compgen -W "${stacks}" -- ${cur}) )
return 0
;;
-Dorg.jboss.ejb3.remoting.IsLocalInterceptor.passByRef=*|-Dcom.sun.management.jmxremote.authenticate=*|-Dcom.sun.management.jmxremote.ssl=*)
cur=${cur#*=}
local booleans="true false"
COMPREPLY=( $(compgen -W "${booleans}" -- ${cur}) )
return 0
;;
-Djboss.server.base.dir=*|-Djboss.home.dir=*|-Djboss.domain.base.dir=*)
cur=${cur#*=}
_filedir -d
return 0
;;
-Djboss.domain.master.address=*|-Djboss.bind.address*=*)
cur=${cur#*=}
_bindingAddress
return 0
;;
--server-config=*|-c=|--host-config=*)
cur=${cur#*=}
_serverProfiles
return 0
esac
case $prev in
-u)
# a few from RFC 2365 IPv4 Local Scope ()
local addresses="239.255.0.1 239.255.0.2 239.255.0.3"
COMPREPLY=( $(compgen -W "${addresses}" -- ${cur}) )
return 0
;;
-b*)
_bindingAddress
return 0
;;
-c)
_serverProfiles
return 0
;;
*)
;;
esac
# *** from jboss5 ********************
# *** -modulepath -c -m -g -l -d -p -n -B -L -C -Djboss.platform.mbeanserver -Djboss.server.base.directory
# *** -Djboss.Domain -Djboss.modcluster.proxyList -Djboss.jvmRoute -Djboss.default.jgroups.stack -Dorg.jboss.ejb3.remoting.IsLocalInterceptor.passByRef -Djboss.platform.mbeanserver -Dcom.sun.management.jmxremote.port -Dcom.sun.management.jmxremote.ssl
# *************************************
# standard commands for standalone and domain mode
local commandsWithoutEqualSign='-b -bmanagement -bunsecure -bpublic --admin-only -h -help -u -version -V -v'
local commandsWithEqualSign='-P -Djboss.node.name -Djboss.home.dir -Djboss.socket.binding.port-offset -Djboss.bind.address.management -Djboss.bind.address -Djboss.bind.address.unsecure'
if [[ $COMP_WORDS == *standalone.sh* ]]
then
commandsWithoutEqualSign="${commandsWithoutEqualSign} -c"
commandsWithEqualSign="${commandsWithEqualSign} --server-config -Djboss.server.base.dir -c"
else
# assume is domain.sh
commandsWithoutEqualSign="${commandsWithoutEqualSign} --backup --cached-dc"
commandsWithEqualSign="${commandsWithEqualSign} -Djboss.domain.master.address --host-config -Djboss.domain.master.port -Djboss.domain.base.dir "
fi
COMPREPLY=( $( compgen -W "$commandsWithoutEqualSign" -- "$cur" )
$( compgen -W "$commandsWithEqualSign" -S '=' -- "$cur" ) )
return 0
}
complete -o nospace -F _jboss standalone.sh
complete -o nospace -F _jboss domain.sh

View File

@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at ugurozyilmazel@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Uğur "vigo" Özyılmazel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,70 @@
# Bash Completion for Atom Package Manager (apm)
If you use [Atom](http://atom.io) editor, you'll like this completion helper.
## Installation
You can install via [Homebrew](http://brew.sh)
brew install homebrew/completions/apm-bash-completion
## Usage
```bash
$ apm [TAB]
clean featured ln remove unlink
config help lns rm unpublish
dedupe home login search unstar
deinstall init ls show update
delete install open star upgrade
dev link outdated starred view
develop linked publish stars
docs links rebuild test
erase list rebuild-module-cache uninstall
$ apm publish
build major minor patch
$ apm config
delete edit get list set
```
## Manual Usage
Just get the file `apm` and call `source apm` (or add it to your bash environment)
---
## Whats New?
Well, I even dont remember this project since Ive got mail today about
missing LICENSE file. Feel free to contribute, add missing pieces :)
---
## Contribution
Please let me know if you need some more options. Please create an issue and
make a request. Also If you like to improve or add more features please fork
it and you know the rest :)
1. Fork it ( https://github.com/vigo/apm-bash-completion )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
---
## Contributer(s)
* [Uğur "vigo" Özyılmazel](https://github.com/vigo) - Creator, maintainer
---
## License
This project is licensed under MIT
---

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# this is the modified version of bundle bash-completion.
# Copyright (c) 2011-2013 Daniel Luz <dev at mernen dot com> (bundle bash-completion)
#
# apm bash-completion is written by Ugur Ozyilmazel
# github: @vigo, twitter: @vigobronx
# enjoy!
#
# you need to activate this via
# $ source apm
__apm(){
local cur prev options apm_command
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
__apm_get_command
if [[ $cur = -* ]]; then
options="--color"
if [[ -z $apm_command ]]; then
options="$options --version --help"
fi
if [[ $apm_command && $apm_command = publish ]]; then
options="--tag --rename"
fi
else
if [[ -z $apm_command || $apm_command = help ]]; then
options="help clean config dedupe deinstall delete dev develop docs erase featured home init install link linked links list ln lns login ls open outdated publish rebuild rebuild-module-cache remove rm search show star starred stars test uninstall unlink unpublish unstar update upgrade view"
fi
if [[ $apm_command && $apm_command = publish ]]; then
options="major minor patch build"
fi
if [[ $apm_command && $apm_command = config ]]; then
options="set get delete list edit"
fi
fi
COMPREPLY=($(compgen -W "$options" -- "$cur"))
}
__apm_get_command() {
local i
for ((i=1; i < $COMP_CWORD; ++i)); do
local arg=${COMP_WORDS[$i]}
case $arg in
[^-]*)
apm_command=$arg
return;;
--version)
apm_command=-
return;;
--help)
apm_command=help
return;;
publish)
apm_command=publish
return;;
config)
apm_command=config
return;;
esac
done
}
complete -F __apm -o bashdefault -o default apm