Аутокоманди, vimscript

6 април 2023

Административни неща

Преговор

Преговор

Преговор

Малко конфигурация на плъгини

Довършване на defaults.vim

Безинтересни за мен, но какво значат?

Довършване на defaults.vim

Безинтересни за мен, но какво значат?

Kind of интересно:

Aside: разбиване на редове

Backslash на следващия ред означава, че се комбинира с предния ред. Да, странно е.

1 2 3 4 5 6 7
command! -nargs=* -range=0 Grep call grep#Run(<count>, <q-args>)

command! -nargs=* -range=0
      \ Grep call grep#Run(<count>, <q-args>)

command! -nargs=* -range=0 Grep
      \ call grep#Run(<count>, <q-args>)

Довършване на defaults.vim

Аутокоманди!

Autocmd, augroup

1 2 3 4 5
augroup MyCustomName
  autocmd!

  autocmd <event> <pattern> <command>
augroup END

Функциите и командите имат име, затова имаме function! <name> и command! <name>. Индивидуални аутокоманди няма как да се зачистват без именувана група.

Pattern (обикновено) описва файла, който е trigger-нал аутокомандата, често няма значение и ще бъде *, което е "каквото и да е". :help autocmd-patterns, но сигурно ще ги говорим по-натам.

Примери: Undoquit

1
autocmd QuitPre * call undoquit#SaveWindowQuitHistory()

Примери: Typewriter

1 2 3 4 5 6
augroup Typewriter
  autocmd!
  autocmd TextChangedI,TextChangedP * call s:Click()
  autocmd InsertEnter * call sound_playfile(s:carriage)
  autocmd InsertLeave * call sound_playfile(s:ding)
augroup END

Примери: Sarcasm mode

"THis iS A Very uSEFul PLUgin"

1
autocmd InsertCharPre * if rand() % 2 | let v:char = toupper(v:char) | endif

Примери: "Редактиране" на mp3ки

1 2
autocmd BufReadCmd *.mp3  call id3#ReadMp3(expand('<afile>'))
autocmd BufWriteCmd *.mp3 call id3#UpdateMp3(expand('<afile>'))

Autocmd

Пълен списък: :help autocmd-events

Autocmd: дебъгване

Autocmd: дебъгване

Autocmd: дебъгване

Autocmd: дебъгване

Filetypes

Ако искаме да променяме настройки за специфични типове файлове? Един вариант:

1 2 3
autocmd FileType ruby   set expandtab   shiftwidth=2 softtabstop=2
autocmd FileType python set expandtab   shiftwidth=4 softtabstop=4
autocmd FileType go     set noexpandtab shiftwidth=4 tabstop=4

Ftplugin

Друг (по-чест) вариант:

Ftplugin

Ftplugin

Ftplugin

Ftplugin

Statusline: за да виждаме filetype-а

:help statusline

Statusline: за да виждаме filetype-а

:help statusline

Statusline: за да виждаме filetype-а

:help statusline

Ftplugin: Базов detection

Директорията "ftdetect" съдържа файлове, които се оценяват с цел detection (:help ftdetect)

1 2
" ~/.vim/ftdetect/notes.vim
autocmd BufNewFile,BufRead *.notes set filetype=notes

Ftplugin: Dot notation

Можем да си направим "комбиниран" тип:

1 2
" ~/.vim/ftdetect/rspec.vim
autocmd BufNewFile,BufRead *_spec.rb set filetype=rspec.ruby

Това ще изпълни ftplugin скриптовете и на "rspec" типа, и на "ruby" типа ("dot notation")

Ftplugin: setfiletype

1 2
" ~/.vim/after/ftdetect/txt.vim
autocmd BufNewFile,BufRead * setfiletype txt

Fallback -- setfiletype е "set-ни filetype, ако не е бил set-нат преди"

Vimscript в повече детайли

Vimscript в повече детайли

Vimscript в повече детайли

Vimscript: числа

Vimscript: числа

Vimscript: числа

Vimscript: числа

Vimscript: Низове

1
echo "Баба\n\"Яга\"\\n"
1 2
Баба
"Яга"\n

Vimscript: Низове

1
echo 'Yaga''s grandma\n'
1
Yaga's grandma\n

Vimscript: Низове

1 2 3
let who = 'Yaga'
echo $"{who}'s grandma"
echo $'Grandma {who}'
1 2
Yaga's grandma
Grandma Yaga

Vimscript: Низове

:help string-functions

Vimscript: Низове

:help string-functions

Vimscript: Низове

:help string-functions

Vimscript: Низове

:help string-functions

Vimscript: Низове

:help string-functions

Vimscript: Булеви стойности

Vimscript: Булеви стойности

Vimscript: Булеви стойности

Vimscript: If-ове

1 2 3 4 5 6 7
if 2 + 2 == 4 && 2 > 1
  echo "Right, that all makes sense"
elseif 2 <= 1
  echo "No, no, that's incorrect"
else
  echo "Now this is completely unexpected"
endif

Vimscript: If-ове

1 2 3 4 5 6 7
if 2 + 2 == 4 && 2 > 1
  echo "Right, that all makes sense"
elseif 2 <= 1
  echo "No, no, that's incorrect"
else
  echo "Now this is completely unexpected"
endif

Има и тернарен оператор: 2 > 1 ? "ok" : "not okay"

Vimscript: If-ове

1 2 3 4 5 6 7
if 2 + 2 == 4 && 2 > 1
  echo "Right, that all makes sense"
elseif 2 <= 1
  echo "No, no, that's incorrect"
else
  echo "Now this is completely unexpected"
endif

Има и тернарен оператор: 2 > 1 ? "ok" : "not okay"
Има и "falsy" оператор: search(...) ?? line('.') (v8.2.1831)

Vimscript: Сравнения (уф)

Vimscript: Сравнения (уф)

Vimscript: Сравнения (уф)

Vimscript: Сравнения (уф)

Vimscript: Сравнения (уф)

Vimscript: Сравнения (уф)

Vimscript: Сравнения (уфффф)

Vimscript: Сравнения (уфффф)

Vimscript: Сравнения (уфффф)

Vimscript: Сравнения (уфффф)

Vimscript: но защо???

Vimscript: но защо???

Vimscript: но защо???

Vimscript: но защо???

Vimscript: решения?

Vimscript: решения?

Vimscript: решения?

Vimscript: решения?

Vimscript: Списъци

Vimscript: Списъци

Vimscript: Slice-ване

:help sublist

1 2 3 4 5 6
let some_list = [1, 2, 3, 4]

let endlist   = some_list[2:]  " от третия елемент нататък: [3, 4]
let shortlist = some_list[2:2] " само третия елемент [3]
let otherlist = some_list[:]   " копие на списъка
let startlist = some_list[:-2] " без последния елемент: [1, 2, 3]

Ако втория индекс е твърде голям, просто се взема списъка до края

Vimscript: Slice-ване

:help sublist

1 2 3 4 5 6
let some_list = [1, 2, 3, 4]

let endlist   = some_list[2:]  " от третия елемент нататък: [3, 4]
let shortlist = some_list[2:2] " само третия елемент [3]
let otherlist = some_list[:]   " копие на списъка
let startlist = some_list[:-2] " без последния елемент: [1, 2, 3]

Ако втория индекс е твърде голям, просто се взема списъка до края
Fun fact: тези работят и за низове, но работят по байтове, което може да е рисковано.

Vimscript: Сравнение на списъци

Vimscript: Unpack-ване на списъци

1 2 3 4
let some_list = ['foo', 'bar', 'baz']

let [f, br, bz] = some_list
let [f; rest]   = some_list

Vimscript: Промяна на списъци

:help list-modification

Vimscript: Промяна на списъци

:help list-modification

Vimscript: Промяна на списъци

:help list-modification

Vimscript: Промяна на списъци

:help list-modification

Vimscript: Итериране на списъци

1 2 3 4 5 6
for item in [1, 2, 3]
  echo "Ей го на: " .. item
endfor
" Ей го на: 1
" Ей го на: 2
" Ей го на: 3

Vimscript: Итериране на списъци

1 2 3 4 5 6
for item in range(1, 3)
  echo "Ей го на: " .. item
endfor
" Ей го на: 1
" Ей го на: 2
" Ей го на: 3

:help range(

Vimscript: Итериране на списъци

1 2 3 4 5 6
for [index, item] in [[0, "foo"], [1, "bar"], [2, "baz"]]
  echo index .. ") Ей го на: " .. item
endfor
" 0) Ей го на: foo
" 1) Ей го на: bar
" 2) Ей го на: baz

Vimscript: Речници

:help Dict

Vimscript: Речници

:help Dict

1 2 3 4 5 6 7
let stuff = { 'foo': 1, 'bar': 2, 'baz': 3 }

let stuff = {
      \ 'foo': 1,
      \ 'bar': 2,
      \ 'baz': 3,
      \ }

Vimscript: Речници

:help Dict

1 2 3 4 5 6 7
let stuff = { 'foo': 1, 'bar': 2, 'baz': 3 }

let stuff = {
      \ 'foo': 1,
      \ 'bar': 2,
      \ 'baz': 3,
      \ }

Важно! Ключа винаги е низ:

1 2 3
let stuff = { 1: 'foo', 3.14: 'bar' }
echomsg string(stuff)
" {'1': 'foo', '3.14': 'bar'}

Vimscript: Речници

Ключа също така е "expression":

1 2
let f = "foo"
let stuff = { f: 1, 'bar': 2, 'baz': 3 }

Vimscript: Речници

Ключа също така е "expression":

1 2
let f = "foo"
let stuff = { f: 1, 'bar': 2, 'baz': 3 }

Ако искаме низове без кавички, може да използваме #{

1 2 3 4 5 6 7
let stuff = #{ foo: 1, bar: 2, baz: 3 }

let stuff = #{
      \ foo: 1,
      \ bar: 2,
      \ baz: 3,
      \ }

Vimscript: Речници

Четене и писане:

1 2 3 4 5
let value = stuff['foo']
let value = stuff.bar

let stuff['foo'] = 100
let stuff.bar = 200

Vimscript: Итериране на речници

1 2 3 4 5 6 7 8
let stuff = { 'foo': 1, 'bar': 2, 'baz': 3 }

for key in keys(stuff)
  echo "Ей ти ключове: " .. key
endfor
" Ей ти ключове: foo
" Ей ти ключове: baz
" Ей ти ключове: bar

Vimscript: Итериране на речници

1 2 3 4 5 6 7 8
let stuff = { 'foo': 1, 'bar': 2, 'baz': 3 }

for value in values(stuff)
  echo "Ей ти стойности: " .. value
endfor
" Ей ти стойности: 1
" Ей ти стойности: 3
" Ей ти стойности: 2

Vimscript: Итериране на речници

1 2 3 4 5 6 7 8
let stuff = { 'foo': 1, 'bar': 2, 'baz': 3 }

for [key, value] in items(stuff)
  echo $"Ей ти ключове и стойности: {key}, {value}"
endfor
" Ей ти ключове и стойности: foo, 1
" Ей ти ключове и стойности: baz, 3
" Ей ти ключове и стойности: bar, 2

Vimscript: Функции за речници

Vimscript: Функции за речници

Vimscript: Функции

1 2 3 4 5 6
function! Add(left, right)
  return a:left + a:right
endfunction

echo Add(2, 3)
" => 5

Vimscript: Функции

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
function! Add(...)
  echo $"Брой на аргументите:       {a:0}"
  echo $"Първи аргумент:            {a:1}"
  echo $"Втори аргумент:            {a:2}"
  echo $"Всички аргументи в списък: {string(a:000)}"

  let sum = 0

  for input in a:000
    let sum += input
  endfor

  return sum
endfunction

echo Add(2, 3, 5, 8, 7)
" Брой на аргументите:       5
" Първи аргумент:            2
" Втори аргумент:            3
" Всички аргументи в списък: [2, 3, 5, 8, 7]
" 25

Vimscript: Функции

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
function! Add(...)
  echo $"Брой на аргументите:       {a:0}"
  echo $"Първи аргумент:            {a:1}"
  echo $"Втори аргумент:            {a:2}"
  echo $"Всички аргументи в списък: {string(a:000)}"

  " За ентусиастите, но за това по-нататък
  return reduce(a:000, { acc, val -> acc + val }, 0)
endfunction

echo Add(2, 3, 5, 8, 7)
" Брой на аргументите:       5
" Първи аргумент:            2
" Втори аргумент:            3
" Всички аргументи в списък: [2, 3, 5, 8, 7]
" 25

Vimscript: Извикване на функции

1 2
call Add(1, 2)
call call('Add', [1, 2])

Vimscript: Извикване на функции

1 2
call Add(1, 2)
call call('Add', [1, 2])
1 2 3
let Plus = function('Add')
call Plus(1, 2)
call call(Plus, [1, 2])

Vimscript: Извикване на функции

1 2
call Add(1, 2)
call call('Add', [1, 2])
1 2 3
let Plus = function('Add')
call Plus(1, 2)
call call(Plus, [1, 2])
1 2
echomsg string(Plus)
" function('Add')

Vimscript: Извикване на функции

ама едно такова като ООП, kind of

1 2 3 4 5 6 7
echo 1->Add(2)
" call 1->Add(2) -- не работи

echo uniq(sort(add([2, 1, 1, 4], 3)))
echo [2, 1, 1, 4]->add(3)->sort()->uniq()
" [1, 2, 3, 4]
" [1, 2, 3, 4]

Повече "ООП, kind of", по-нататък

Vimscript: Засега толкоз

Vimscript: Засега толкоз

Има още много, но това би трябвало да ви стигне, за да:

Vimscript: Засега толкоз

Има още много, но това би трябвало да ви стигне, за да:

Въпроси