Как да използвате Vi/Vim редактора в Ubuntu: Пълно техническо ръководство
Vi и Vim (Vi Improved) са модални текстови редактори, управлявани с клавиатура, които работят изцяло в терминала, което ги прави незаменими за администриране на сървъри, редактиране на конфигурации от разстояние и работни процеси за скриптиране в Ubuntu и други Linux дистрибуции. Vim разширява Vi със синтактично оцветяване, многостепенно отмяна, разделени прозорци, поддръжка на плъгини и конфигурируем скриптов слой — като същевременно консумира незначителни системни ресурси.
Ако управлявате среда за VPS Хостинг или физически сървър, владеенето на Vim не е по избор — то е основно умение. SSH сесиите не винаги имат достъп до графичен интерфейс, а Vim е почти универсално наличен на всяка Unix-базирана система, с която ще работите.
Защо Vim все още доминира в сървърните среди
Съвременните IDE са мощни, но са без значение, когато сте свързани към headless Ubuntu сървър чрез SSH в 2 часа сутринта, отстранявайки повредена Nginx конфигурация. Модалният дизайн на Vim означава, че всяко натискане на клавиш е команда — няма зависимост от мишка, няма разход за рендиране и няма латентност, въведена от графичен слой.
Основни причини системните администратори да разчитат на Vim:
- Нулеви външни зависимости: Работи при всяка SSH връзка, включително такива с ниска честотна лента или висока латентност
- Последователна наличност: Предварително инсталиран или тривиално инсталируем на Debian, Ubuntu, CentOS, Alpine и практически всяка Linux дистрибуция
- Скорост в мащаб: Редактирането на конфигурационни файлове, лог файлове или скриптове с хиляди редове е по-бързо в Vim, отколкото в какъвто и да е GUI редактор, след като мускулната памет е изградена
- Скриптируемост: Вграденият скриптов език на Vim (Vimscript) и поддръжката на Lua (в Neovim) позволяват пълна автоматизация на повтарящи се задачи за редактиране
Инсталиране на Vim в Ubuntu
Ubuntu се доставя с минимален пакет `vim-tiny`, на който липсват синтактично оцветяване, поддръжка на множество файлове и много разширени функции. За пълна функционалност инсталирайте пълния пакет:
“`bash
sudo apt update
sudo apt install vim -y
“`
За да проверите инсталираната версия и да потвърдите пълната поддръжка на функции:
“`bash
vim –version
“`
Потърсете `+syntax`, `+clipboard`, `+python3` и `+multi_byte` в флаговете за функции. Префикс `-` означава, че тази функция е изключена от бинарния файл. Ако имате нужда от тези функции и те липсват, инсталирайте `vim-gtk3` или `vim-nox` вместо това:
“`bash
sudo apt install vim-nox -y # Headless full-feature build
sudo apt install vim-gtk3 -y # GTK3 build with clipboard integration
“`
Критичен граничен случай: При минимални образи на Ubuntu сървър — като тези, използвани в Docker контейнери или cloud-init bootstrapped Dedicated Servers — дори `vi` може да липсва. В такъв случай инсталирайте `vim` изрично преди да опитате да редактирате конфигурационни файлове.
Отваряне, създаване и възстановяване на файлове
“`bash
vim filename.txt # Open existing file or create new one
vim /etc/nginx/nginx.conf # Open a system configuration file (use sudo if needed)
sudo vim /etc/ssh/sshd_config # Edit privileged files
vim +42 filename.txt # Open file and jump directly to line 42
vim +/searchterm file.txt # Open file with cursor on first match of searchterm
“`
Възстановяване от swap файл: Vim автоматично създава скрит swap файл (`.filename.txt.swp`) по време на редактиране. Ако сесията ви се срине или SSH връзката се прекъсне, отворете отново същия файл и Vim ще ви подкани да възстановите незапазените промени. Винаги избирайте `(R)ecover` първо, запазете възстановеното съдържание, след което изтрийте swap файла с `:e`, последвано от `:!rm ~/.filename.txt.swp` или като изпълните `vim -r filename.txt`.
Този механизъм за възстановяване е особено ценен при редактиране на критични конфигурационни файлове на производствени сървъри — прекъсната връзка не означава загубена работа.
Разбиране на модалната архитектура на Vim
Модалният дизайн на Vim е единствената най-важна концепция за усвояване. За разлика от стандартните редактори, при които всяко натискане на клавиш вмъква символ, Vim разделя навигацията, редактирането и изпълнението на команди в отделни режими.
| Режим | Активиране | Основна цел |
|---|
| — | — | — |
|---|
| **Normal** | `Esc` (по подразбиране при отваряне) | Навигация, изтриване, копиране, поставяне, изпълнение на макроси |
|---|
| **Insert** | `i`, `a`, `o`, `O`, `I`, `A` | Въвеждане и вмъкване на текст |
|---|
| **Visual** | `v` (символ), `V` (ред), `Ctrl+v` (блок) | Избиране на текстови диапазони |
|---|
| **Visual Block** | `Ctrl+v` | Избиране и редактиране по колони |
|---|
| **Command-Line** | `:` | Файлови операции, търсене/замяна, настройки, външни команди |
|---|
| **Replace** | `R` | Презаписване на съществуващи символи |
|---|
| **Ex** | `Q` | Пакетно изпълнение на команди (рядко се използва интерактивно) |
|---|
Най-честата грешка на начинаещите е натискането на клавиши в Normal режим с очакване да се появи текст, след което паника, когато `dd` изтрива ред или `gg` прескача към началото на файла. Винаги потвърждавайте текущия си режим, като проверявате долния ляв ъгъл на екрана — Insert режимът показва `– INSERT –`, Visual режимът показва `– VISUAL –`, а Normal режимът не показва нищо.
Команди за навигация в Normal режим
Ефективната навигация е това, което разграничава потребителя на Vim, който е просто функционален, от този, който е наистина бърз. Научете ги по ред на приоритет:
Основно движение на курсора
| Клавиш | Действие |
|---|
| — | — |
|---|
| `h` | Преместване с един символ наляво |
|---|
| `l` | Преместване с един символ надясно |
|---|
| `j` | Преместване с един ред надолу |
|---|
| `k` | Преместване с един ред нагоре |
|---|
| `w` | Прескачане към началото на следващата дума |
|---|
| `b` | Прескачане към началото на предишната дума |
|---|
| `e` | Прескачане към края на текущата дума |
|---|
| `0` | Прескачане към началото на реда |
|---|
| `^` | Прескачане към първия символ без интервал в реда |
|---|
| `$` | Прескачане към края на реда |
|---|
Навигация на ниво файл
| Клавиш | Действие |
|---|
| — | — |
|---|
| `gg` | Прескачане към първия ред на файла |
|---|
| `G` | Прескачане към последния ред на файла |
|---|
| `:42` | Прескачане към ред 42 |
|---|
| `Ctrl+f` | Превъртане с една пълна страница напред |
|---|
| `Ctrl+b` | Превъртане с една пълна страница назад |
|---|
| `Ctrl+d` | Превъртане с половин страница надолу |
|---|
| `Ctrl+u` | Превъртане с половин страница нагоре |
|---|
| `%` | Прескачане към съответстваща скоба, кръгла скоба или фигурна скоба |
|---|
| `*` | Прескачане към следващото срещане на думата под курсора |
|---|
| `#` | Прескачане към предишното срещане на думата под курсора |
|---|
Съвет за напреднали потребители: Поставете число пред всяка команда за движение, за да я повторите. `5j` се премества 5 реда надолу. `3w` прескача 3 думи напред. `10dd` изтрива 10 реда. Този числов множител се прилага към практически всяка команда в Normal режим и е ключът към редактиране с висока скорост.
Влизане и излизане от Insert режим
| Клавиш | Поведение |
|---|
| — | — |
|---|
| `i` | Вмъкване преди курсора |
|---|
| `a` | Добавяне след курсора |
|---|
| `I` | Вмъкване в началото на реда |
|---|
| `A` | Добавяне в края на реда |
|---|
| `o` | Отваряне на нов ред отдолу и влизане в Insert режим |
|---|
| `O` | Отваряне на нов ред отгоре и влизане в Insert режим |
|---|
| `s` | Изтриване на символа под курсора и влизане в Insert режим |
|---|
| `S` | Изтриване на целия ред и влизане в Insert режим |
|---|
| `Esc` или `Ctrl+[` | Връщане към Normal режим |
|---|
Критичен навик: Развийте рефлекса да натискате `Esc` веднага след завършване на вмъкване на текст. Оставането в Insert режим, когато възнамерявате да навигирате, е причината за повечето случайни редакции.
Запазване, излизане и управление на файлове
Тези команди се изпълняват от Command-Line режим (натиснете `:` първо):
| Команда | Действие |
|---|
| — | — |
|---|
| `:w` | Запазване (запис) на текущия файл |
|---|
| `:w filename.txt` | Запазване с ново име на файл |
|---|
| `:q` | Излизане (само ако няма незапазени промени) |
|---|
| `:q!` | Принудително излизане, отхвърляйки всички незапазени промени |
|---|
| `:wq` или `:x` | Запазване и излизане |
|---|
| `ZZ` | Запазване и излизане (бърз клавиш в Normal режим) |
|---|
| `ZQ` | Излизане без запазване (бърз клавиш в Normal режим) |
|---|
| `:w !sudo tee %` | Запазване на файл, отворен без sudo привилегии |
|---|
Трикът `:w !sudo tee %` е задължително знание за системните администратори. Когато отворите системен файл като `/etc/fstab` без sudo и направите промени, не можете да запазите с `:w`. Тази команда пренасочва съдържанието на буфера през `sudo tee` за запис на файла с повишени привилегии — без да е необходимо да затваряте и отваряте отново Vim.
Операции за редактиране: изтриване, копиране, поставяне и отмяна
Моделът за редактиране на Vim е изграден върху оператори + движения. Оператор (като `d` за изтриване или `y` за yank/копиране), комбиниран с движение (като `w` за дума или `$` за края на реда), създава прецизно действие за редактиране.
Основни команди за редактиране
| Команда | Действие |
|---|
| — | — |
|---|
| `x` | Изтриване на символа под курсора |
|---|
| `X` | Изтриване на символа преди курсора |
|---|
| `dd` | Изтриване (изрязване) на целия текущ ред |
|---|
| `D` | Изтриване от курсора до края на реда |
|---|
| `dw` | Изтриване от курсора до края на думата |
|---|
| `d$` | Изтриване от курсора до края на реда |
|---|
| `d0` | Изтриване от курсора до началото на реда |
|---|
| `yy` или `Y` | Yank (копиране) на целия текущ ред |
|---|
| `yw` | Yank от курсора до края на думата |
|---|
| `p` | Поставяне след курсора (или под текущия ред при line-wise yanks) |
|---|
| `P` | Поставяне преди курсора (или над текущия ред) |
|---|
| `u` | Отмяна на последната промяна |
|---|
| `Ctrl+r` | Повторно прилагане на последната отменена промяна |
|---|
| `.` | Повтаряне на последната промяна (една от най-мощните команди в Vim) |
|---|
| `~` | Превключване на регистъра на символа под курсора |
|---|
| `>>` | Увеличаване на отстъпа на текущия ред с едно ниво |
|---|
| `<<` | Намаляване на отстъпа на текущия ред с едно ниво |
|---|
Командата `.` (точка) е вероятно най-недооценяваната функция на Vim сред начинаещите. Тя повтаря последното ви съставно действие — ако сте изтрили дума с `dw`, натискането на `.` изтрива следващата дума. Ако сте променили дума с `cw` и сте въвели замяна, `.` прилага същата замяна към следващото срещане. Това елиминира повтарящите се ръчни редакции в големи файлове.
Visual режим: прецизен избор на текст
Visual режимът предоставя три степени на гранулярност при избора:
- `v` — Визуален избор по символи
- `V` — Визуален избор по редове (избира цели редове)
- `Ctrl+v` — Блоков визуален избор (редактиране по колони)
След като направите избор, приложете оператори:
| Клавиш | Действие върху избора |
|---|
| — | — |
|---|
| `d` | Изтриване на избрания текст |
|---|
| `y` | Yank (копиране) на избрания текст |
|---|
| `c` | Промяна (изтриване и влизане в Insert режим) |
|---|
| `>` | Увеличаване на отстъпа на избора |
|---|
| `<` | Намаляване на отстъпа на избора |
|---|
| `~` | Превключване на регистъра на избора |
|---|
| `:` | Влизане в Command-Line режим с предварително попълнен диапазон |
|---|
Реален случай на употреба на блоков visual режим (`Ctrl+v`): Имате конфигурационен файл, в който трябва да коментирате 15 последователни реда, като добавите `#` в началото. Изберете първата колона на тези редове с `Ctrl+v`, навигирайте надолу с `j`, натиснете `I` (главно i), въведете `#`, след което натиснете `Esc`. Vim прилага вмъкването към всеки избран ред едновременно. Това е задача, която би изисквала regex или ръчно повторение в повечето други редактори.
Търсене и замяна
Търсене
“`
/pattern Search forward for pattern (regex supported)
?pattern Search backward for pattern
n Jump to next match
N Jump to previous match
- Search forward for word under cursor
Search backward for word under cursor
:noh Clear search highlighting
“`
Синтаксис за търсене и замяна
“`
:%s/old/new/g Replace all occurrences in entire file
:%s/old/new/gc Replace all with confirmation prompt for each
:%s/old/new/gi Case-insensitive replace across entire file
:10,20s/old/new/g Replace only within lines 10 through 20
:'<,'>s/old/new/g Replace within visually selected range
:%s/bwordb/new/g Replace whole word only (word boundary anchors)
“`
Поддръжка на Regex: Vim използва собствен диалект на regex. Границата на думата `b`, `d` за цифри, `s` за интервали и `+` (едно или повече) са налични. За разширен синтаксис на regex, поставете префикс `v`: `:%s/v(foo|bar)/baz/g` съвпада с "foo" или "bar" и ги замества с "baz".
Работа с множество файлове, буфери и разделени прозорци
Тук мощта на Vim става най-очевидна при сложни сесии за редактиране.
Буфери
Буферът е представяне на файл в паметта. Vim може да държи много буфери отворени едновременно.
“`
:e filename Open a file into a new buffer
:ls or :buffers List all open buffers
:b2 Switch to buffer number 2
:bnext or :bn Switch to next buffer
:bprev or :bp Switch to previous buffer
:bd Delete (close) current buffer
“`
Разделени прозорци
“`
:split filename Horizontal split, open file in upper pane
:vsplit filename Vertical split, open file in right pane
Ctrl+w h/j/k/l Navigate between split panes
Ctrl+w = Equalize split pane sizes
Ctrl+w q Close current pane
“`
Табове
“`
:tabnew filename Open file in a new tab
:tabnext or gt Switch to next tab
:tabprev or gT Switch to previous tab
:tabclose Close current tab
“`
Практически сценарий: При редактиране на конфигурацията на уеб сървър на VPS с cPanel, може да се наложи да се обърнете към основния `nginx.conf` докато редактирате файл за виртуален хост. Отворете и двата в вертикален split с `:vsplit /etc/nginx/nginx.conf` и навигирайте между панелите с `Ctrl+w l` и `Ctrl+w h` — без да е необходимо да затваряте единия файл, за да прегледате другия.
Конфигуриране на Vim с .vimrc
Файлът `.vimrc` в домашната ви директория е постоянната конфигурация на Vim. Той се изпълнява като Vimscript всеки път, когато Vim стартира.
“`bash
vim ~/.vimrc
“`
Препоръчителна конфигурация за производствен сървър
“`vim
" Display settings
set number " Show absolute line numbers
set relativenumber " Show relative line numbers (great for jump commands)
set cursorline " Highlight the current line
set scrolloff=8 " Keep 8 lines visible above/below cursor when scrolling
" Indentation
set autoindent " Copy indent from current line on new line
set smartindent " Context-aware indentation for code
set expandtab " Convert tabs to spaces
set tabstop=4 " Tab width = 4 spaces
set shiftwidth=4 " Indentation width for >> and <<
" Search behavior
set hlsearch " Highlight all search matches
set incsearch " Show matches as you type
set ignorecase " Case-insensitive search
set smartcase " Override ignorecase if search contains uppercase
" Usability
set mouse=a " Enable mouse in all modes
syntax on " Enable syntax highlighting
set encoding=utf-8 " Default encoding
set clipboard=unnamedplus " Use system clipboard for yank/paste
set undofile " Persist undo history across sessions
set undodir=~/.vim/undo " Directory for persistent undo files
" Visual
set showmatch " Briefly jump to matching bracket
set laststatus=2 " Always show status line
set wildmenu " Enhanced command-line completion
“`
Важно: Директивата `set undofile` създава постоянна история на отмяната, съхранена на диска. Това означава, че можете да затворите файл, да го отворите отново дни по-късно и все още да отменяте промени от предишната сесия. Създайте директорията за отмяна преди да активирате това:
“`bash
mkdir -p ~/.vim/undo
“`
Това е особено ценно при извършване на постепенни промени в конфигурационни файлове на производствени системи — например при настройка на PHP-FPM параметри или коригиране на SSL параметри на сървър, изпълняващ SSL Сертификати за множество домейни.
Макроси: автоматизиране на повтарящи се редакции
Макросите са една от най-мощните и най-малко използвани функции на Vim. Макросът записва последователност от натискания на клавиши и ги възпроизвежда.
“`
qa Start recording macro into register 'a'
[actions] Perform any sequence of Normal/Insert mode commands
q Stop recording
@a Replay macro stored in register 'a'
@@ Replay the last executed macro
10@a Replay macro 'a' ten times
“`
Реален пример: Имате CSV файл с 200 реда и трябва да оградите второто поле на всеки ред в двойни кавички. Запишете макроса на първия ред, възпроизведете го 199 пъти с `199@a` и трансформацията е завършена за по-малко от секунда. Не е необходим скрипт.
Маркери и прескачания
Маркерите ви позволяват да отбелязвате позиции в файл и да се връщате към тях незабавно.
“`
ma Set mark 'a' at current cursor position
'a Jump to the line of mark 'a'
`a Jump to the exact position of mark 'a'
'' Jump back to position before last jump
Ctrl+o Jump to previous position in jump list
Ctrl+i Jump to next position in jump list
:marks List all current marks
“`
Vim срещу Nano срещу Emacs: избор на правилния терминален редактор
| Функция | Vim | Nano | Emacs |
|---|
| — | — | — | — |
|---|
| **Крива на обучение** | Стръмна (модална система) | Минимална | Много стръмна |
|---|
| **Време за стартиране** | Почти мигновено | Почти мигновено | По-бавно |
|---|
| **Използване на памет** | Много ниско | Много ниско | Умерено до високо |
|---|
| **Синтактично оцветяване** | Пълно | Основно | Пълно |
|---|
| **Екосистема от плъгини** | Обширна | Минимална | Обширна |
|---|
| **Поддръжка на макроси** | Вградена, мощна | Няма | Вградена |
|---|
| **Разделени прозорци** | Да | Не | Да |
|---|
| **Отдалечено редактиране** | Чрез SSH нативно | Чрез SSH нативно | TRAMP протокол |
|---|
| **Сложност на конфигурацията** | Умерена (.vimrc) | Минимална | Висока (Elisp) |
|---|
| **Най-подходящ за** | Напреднали потребители, системни администратори | Бързи редакции, начинаещи | Разработчици, потребители на Lisp |
|---|
За задачи по администриране на сървъри — редактиране на конфигурационни файлове, писане на shell скриптове, преглед на логове — Vim осигурява най-добрия баланс между мощ, наличност и скорост. Nano е приемлив за еднократни редакции, когато не можете да си позволите когнитивното натоварване. Emacs е легитимен избор за разработчици, които живеят в терминала, но неговото потребление на ресурси и времето за стартиране го правят по-малко практичен в ограничени сървърни среди.
Чести грешки и как да ги избегнете
1. Редактиране на производствени файлове без резервно копие
Винаги създавайте резервно копие преди редактиране на критични системни файлове:
“`bash
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
sudo vim /etc/nginx/nginx.conf
“`
2. Забравяне да се използва sudo
Ако отворите привилегирован файл без sudo и направите промени, използвайте `:w !sudo tee %` за запазване без загуба на редакциите ви.
3. Объркване на регистрите
Когато изтриете текст с `dd`, той отива в регистъра по подразбиране `"`. Ако след това копирате нещо с `yy`, изтритият текст се презаписва. За да запазите копие преди изтриване, използвайте именувани регистри: `"ayy` копира в регистър `a`, а `"ap` поставя от него.
4. Оставяне на swap файлове на споделени системи
Vim swap файловете в `/tmp` или работната директория могат да объркат други потребители или автоматизирани процеси. Конфигурирайте специална директория за swap в `.vimrc`:
“`vim
set directory=~/.vim/swap//
“`
Двойното завършващо наклонено черта кара Vim да кодира пълния път на файла в името на swap файла, предотвратявайки колизии.
5. Проблеми с края на редовете при файлове за различни платформи
Ако редактирате файл, създаден в Windows, той може да има CRLF (`rn`) окончания на редовете. Vim ще показва `^M` в края на всеки ред. Поправете това с:
“`bash
:%s/r//g
“`
Практически контролен списък с ключови изводи
Използвайте това като матрица за бързо вземане на решения преди и по време на Vim сесии:
- Преди редактиране на производствен файл: Създайте резервно копие с времеви печат с `cp file file.$(date +%Y%m%d%H%M%S).bak`
- Осъзнаване на режима: Ако натисканията на клавиши не вмъкват текст, натиснете `Esc` и потвърдете режима си
- Навик за бързо запазване: Натиснете `Esc` след това `:w` след всяка значителна промяна — не чакайте до края
- Използвайте `:set number` временно, ако трябва да навигирате до конкретен ред и нямате го в `.vimrc`
- За глобално търсене/замяна: Винаги тествайте с `:%s/old/new/gc` (с потвърждение) преди да изпълните `:%s/old/new/g` без проверка
- Подкана за swap файл при отваряне: Винаги избирайте `(R)ecover`, запазете съдържанието, след което изтрийте swap файла
- За редактиране по колони: Използвайте `Ctrl+v` блоков visual режим вместо ръчно повторение
- Постоянна отмяна: Конфигурирайте `set undofile` в `.vimrc` на всеки сървър, който администрирате редовно
- Интеграция с клипборда: Ако `p` поставя неочаквано съдържание, проверете дали `set clipboard=unnamedplus` е зададено и дали `xclip` или `xsel` е инсталиран
- При съмнение: `:help keyword` отваря вградената документация за всяка команда или опция
Независимо дали управлявате конфигурационни файлове в среди за Споделен Уеб Хостинг или поддържате сложна инфраструктура на Dedicated Servers, ефективността на Vim се натрупва с времето — всяка команда, която усвоите, премахва трудностите от работния ви процес завинаги.
ЧЗВ
В: Каква е разликата между Vi и Vim в Ubuntu?
`vi` в съвременните Ubuntu системи обикновено е символна връзка към `vim` в намален режим на съвместимост или към `vim-tiny`. Истинският Vi е оригиналният редактор от 1976 г. без синтактично оцветяване, без многостепенна отмяна и без поддръжка на плъгини. Vim добавя над 100 функции към Vi, като същевременно остава напълно обратно съвместим с клавишните комбинации на Vi.
В: Как да изляза от Vim, ако съм напълно заседнал?
Натиснете `Esc` няколко пъти, за да се уверите, че сте в Normal режим, след което въведете `:q!` и натиснете Enter. Това принудително излиза без запазване. Ако дори това не успее (рядко, но възможно в рекурсивни командни състояния), натиснете `Ctrl+c` първо, след това `:q!`.
В: Може ли Vim да редактира файлове чрез SSH без да ги копира локално?
Да. Използвайте `vim scp://user@hostname//path/to/file` за директно редактиране на отдалечени файлове чрез SCP. Vim обработва прехвърлянето прозрачно. Алтернативно, използвайте `rsync` за изтегляне на файла, редактиране локално и качване обратно — това е по-бързо за големи файлове.
В: Как да активирам синтактично оцветяване за конкретен тип файл, който Vim не разпознава?
Изпълнете `:set filetype=nginx` (или `python`, `yaml`, `bash` и т.н.) за ръчно задаване на тип файл за текущата сесия. За да го направите постоянно за конкретно файлово разширение, добавете `autocmd BufRead,BufNewFile *.conf set filetype=nginx` към вашия `.vimrc`.
В: Neovim по-добър избор ли е от Vim за използване на сървър?
За чисти задачи по администриране на сървъри стандартният Vim е достатъчен и по-универсално наличен. Neovim предлага конфигурация базирана на Lua, по-добра поддръжка на асинхронни плъгини и вграден LSP клиент — предимства, които имат значение предимно за работни процеси при разработка. На производствени сървъри, където инсталирате само необходимото, Vim остава прагматичният избор.
