El blog de cubells

Cercar per trobar

M'agrada llegir codi d'altres per aprendre. I llig molt abans de preguntar dubtes.

És una forma de treballar que m'ha ensenyat el programari lliure: busca't la vida i després pregunta.

I per què preguntar si tinc milions de línies de codi amb exemples de programadors que saben programar més que jo?

Per això em sembla inaudit, que al munt de llistes de correu on estic apuntat, els nouvinguts del programari propietari, el primer que fan és preguntar. I cada pregunta... Sobre això ja faré un apunt intens els propers dies. M'ho apunte [*].

Ací volia parlar de cercar.

No tinc memòria, i és impossible recordar-se de tot. Així que és normal per mi cercar, en milers de fitxers, el nom de funcions, de paraules clau, etc. en distints formats de fitxer, per tal de trobar exemples, refrescar la sintaxi o aprendre la millor manera de fer les coses.

Fins ara m'havia fet un script en Bash jo mateix al qual li havia posat el nom de tb (trobar):

Bàsicament utilitza la comanda find amb combinació amb la comanda grep per cercar dins de fitxers. Hi ha, si llegiu el codi, 3 possibilitats depenent dels paràmetres. Cercar la cadena en totes les extensions o en una especificada, i després hi havia una altra que era cercar la cadena i afegir n línies, la qual cosa em permetia cercar en la resta de línies per alguna cosa.

Així, si volia trobar la funció default_get() simplement havia d'executar:

cubells@portatil:~/Dades/git/odoo11/src/core/addons/account$ tb py "default_get"
./models/account_payment.py:    def default_get(self, fields):
./models/account_payment.py:        rec = super(account_register_payments, self).default_get(fields)
./models/account_payment.py:    def default_get(self, fields):
./models/account_payment.py:        rec = super(account_payment, self).default_get(fields)
./models/account_bank_statement.py:        company_id = self.env['res.company']._company_default_get('account.bank.statement').id
./models/account_bank_statement.py:        default=lambda self: self.env['res.company']._company_default_get('account.bank.statement'))
./models/chart_template.py:    def default_get(self, fields):
./models/chart_template.py:        res = super(WizardMultiChartsAccounts, self).default_get(fields)
./models/account.py:        default=lambda self: self.env['res.company']._company_default_get('account.account'))
./models/account.py:    def default_get(self, default_fields):
./models/account.py:        return super(AccountAccount, contextual_self).default_get(default_fields)
./models/account_invoice.py:        default=lambda self: self.env['res.company']._company_default_get('account.invoice'))
./models/account_invoice.py:        readonly=True, states={'draft': [('readonly', False)]}) #Default value computed in default_get for out_invoices
./models/account_invoice.py:    def default_get(self,default_fields):
./models/account_invoice.py:        res = super(AccountInvoice, self).default_get(default_fields)
./models/account_move.py:    def default_get(self, fields):
./models/account_move.py:        rec = super(AccountMoveLine, self).default_get(fields)
./wizard/account_reconcile.py:    def default_get(self, fields):
./wizard/account_reconcile.py:        res = super(AccountMoveLineReconcile, self).default_get(fields)

Com veieu, perfecte.

Però cercant per la xarxa i per casualitat he vist millors opcions.

La primera ha estat el programa ack. És una meravella com podeu comprovar:

Per instal·lar simplemente heu de fer apt-get install ack.

Avantatges:

I aquest va ser el nou programa que vaig adoptar.

Però també de casualitat, em vaig trobar amb un programa que és el que actualment faig servir per cercar: ripgrep.

I quina diferència hi ha entre ack i rg? Doncs la velocitat, la qual m'ha encisat. Ripgrep és molt més ràpid que l'ack, com podeu comprovar per a la mateixa cerca:

És de l'ordre de 5 vegades més ràpid.

Per instal·lar simplemente heu de fer apt-get install ripgrep.

També m'ha agradat molt perquè exclou els fitxers inclosos als patrons dels .gitignore durant la cerca directament, o que fa cerca a fitxers unicode.

Així que m'he creat uns quans alies per cercar a les extensions més comuns que utilitze i no haver de posar-la cada vegada:

$ cat ~/.bashrc | grep rg
alias rgp="rg -g '*.py'"
alias rgx="rg -g '*.xml'"
alias rgc="rg -g '*.csv'"
alias rga="rg"

I he afegit una variable al bash per dir-li on està el fitxer de configuració del ripgrep:

$ cat ~/.bashrc | grep RIPGREP
export RIPGREP_CONFIG_PATH=~/.ripgreprc

On he especificat aquestos paràmetres generals:

$ cat ~/.ripgreprc 
───────┬─────────────────────────────────────────────────────────────
       │ File: /home/cubells/.ripgreprc
───────┼─────────────────────────────────────────────────────────────
   1   │ # Don't let ripgrep vomit really long lines to my terminal.
   2   │ --max-columns=150
   3   │ 
   4   │ # Because who cares about case!?
   5   │ --smart-case
   6   │ 
   7   │ # Ignore .gitignore message warnings
   8   │ --no-messages

He afegit el nombre màxim de columnes, que no faça cas de les majúscules i que no mostre els errors en processar els fitxers .gitignore.

Si voleu una bona comparativa, podeu llegir aquesta web, del creador d'ack, una mica antiquada ja pels canvis al programari, però que us pot donar una idea de quina és la millor eina per a vosaltres.

Sense comentaris encara. Comenta ara