Important Announcement
PubHTML5 Scheduled Server Maintenance on (GMT) Sunday, June 26th, 2:00 am - 8:00 am.
PubHTML5 site will be inoperative during the times indicated!

Home Explore 2013_vi_vim_ru

2013_vi_vim_ru

Published by faustkeller, 2017-09-07 00:23:54

Description: 2013_vi_vim_ru

Search

Read the Text Version

Сохранение команд 129 4. Наж­ ать ENTER для пер­ ех­ од­ а на но­вую строк­ у. 5. На­жать ESC, чтоб­ ы за­вер­шить реж­ им встав­ки. 6. Удал­ ить де­фис и  два ок­руж­ аю­щих его про­бел­ а (3x), по­сле че­го сде­ лать след­ ующ­ ее сло­во про­пис­ным (~). Ес­ли эти дей­ств­ ия нужн­ о пов­ то­рить не­скольк­ о раз, то это до­воль­но нуд­ ная ра­бот­ а. С по­мощ­ ью :map мож­но со­хра­нить всю по­след­ о­ва­тельн­ ость, что­бы за­тем выз­ ы­вать ее одн­ им на­жа­тие­ м клав­ иш­ и: :map g I.IP \"^[ea\" 10n^M^[3x~ Обр­ ат­ и­те вним­ ан­ ие, что как ESC, так и ENTER нео­ бх­ од­ им­ о «спрят­ ать» с по­мощ­ ью CTRL-V. По­след­ ов­ ат­ ель­ность ^[ воз­ник­ а­ет по­сле вво­да CTRL- V и  ESC. Ес­ли ввес­ ти CTRL-V и  ENTER, то поя­ вит­ся пос­ лед­ ов­ ат­ ель­ ность ^M. Пос­ ле это­го про­стое наж­ а­тие на g про­из­ве­дет це­лую се­рию ис­правл­ е­ний. Есл­ и связь мед­лен­ная, то вы смож­ ет­ е уви­деть, как про­исх­ од­ ят эти прав­ ки, од­на за друг­ ой. Ес­ли же ка­нал ши­ро­кий (или вы ред­ акт­ и­руе­те файл лок­ аль­но), то это буд­ ет выг­ ля­деть как волш­ ебс­ т­во. Не расс­ траи­вайт­ есь, есл­ и ва­ша пер­вая поп­ ытк­ а за­дать ото­браж­ ен­ ие для клав­ иш­ и не уда­стс­ я. Даж­ е неб­ ольш­ ая ошиб­ка в оп­ред­ ел­ е­нии ото­ браж­ е­ния мож­ ет при­вест­ и к рез­ ульт­ ат­ ам, дал­ ек­ им от ожид­ ае­мых. Вве­ ди­те u для от­мен­ ы прав­ки и поп­ роб­ уй­те все сна­чал­ а.Другие примеры отображения клавиш Сле­дую­щие прим­ ер­ ы по­каз­ ы­ваю­ т нек­ от­ о­рые ра­зумн­ ые со­чет­ ан­ ия кла­ виш, ко­тор­ ые мож­но ис­польз­ о­вать в ото­бра­же­ни­ях: 1. Доб­ ав­ле­ние тек­ста при кажд­ ом пер­ ех­ о­де в кон­ ец слов­ а: :map e ea В боль­шин­ств­ е слу­чае­ в един­ств­ ен­ная прич­ и­на для пер­ ех­ од­ а на кон­ ец слова – до­бавл­ е­ние текс­ та. Эта ото­бра­женн­ ая пос­ ле­дов­ ат­ ель­ность ав­ то­мат­ ич­ е­ски пе­ре­во­дит поль­зов­ а­те­ля в  ре­жим встав­ки. Обр­ а­ти­те вни­ман­ ие, что отоб­ раж­ аем­ ая клав­ иш­ а e уже имее­ т знач­ ен­ ие в  vi. Можн­ о пер­ ео­ п­ред­ е­лять ис­поль­зуе­мую в ре­дакт­ о­ре клав­ и­шу, но пок­ а ра­бот­ ае­ т отоб­ раж­ ен­ ие, обычн­ ое дей­ст­вие этой клав­ и­ши нед­ ост­ упн­ о. В на­шем слу­чае это не страшн­ о, так как E част­ о рав­но­сильн­ а e. 2. Пер­ е­ста­нов­ка двух слов: :map K dwElp Ра­нее в глав­ е мы уже обс­ уж­ д­ ал­ и ана­ло­гичн­ ую по­сле­до­ва­тельн­ ость, од­на­ко сейч­ ас нуж­но исп­ оль­зо­вать E (здесь, как и во всех прим­ ер­ ах ниж­ е, мы по­лаг­ ае­ м, что ком­ ан­да e отоб­ раж­ ен­ а на ea). Не заб­ ыв­ ай­те, что кур­сор долж­ ен стоя­ ть в нач­ а­ле пер­во­го из двух пер­ е­став­ляе­мых слов. К  со­жа­лен­ ию, из-за ко­манд­ ы l эта по­след­ ов­ ат­ ельн­ ость (как

130 Глава 7. Продвинутое редактирование и прив­ е­денн­ ая ра­нее) не бу­дет ра­бот­ ать, есл­ и сло­ва стоя­ т в кон­це стро­ ки, так как во врем­ я вып­ ол­не­ния пос­ ле­дов­ а­тельн­ о­сти курс­ ор поп­ ад­ ет на кон­ ец строк­ и и не мож­ ет стоя­ ть пра­вее. Так что при­вед­ ем ре­шен­ ие пол­ у­чше: :map K dwwP Вме­сто w мож­но исп­ оль­зов­ ать W. 3. Со­хран­ е­ние фай­ла и пе­ре­ход к след­ ующ­ е­му из на­бо­ра: :map q :w^M:n^M Обр­ ат­ и­те вним­ ан­ ие, что можн­ о отоб­ ра­жать на кла­виш­ и ком­ анд­ ы ex, но убед­ и­тесь, что пос­ ле кажд­ ой ко­ман­ды ex сто­ит воз­врат ка­ретк­ и. По­добн­ ая по­сле­дов­ а­тель­ность об­легч­ ит пер­ ем­ е­щен­ ие межд­ у фай­ла­ ми и  приг­ о­дит­ся, есл­ и вы от­кры­ли мно­же­ств­ о не­боль­ших фай­лов од­ной ко­ман­дой vi. Отоб­ раж­ е­ние на бук­ ­ву q по­мо­жет за­помн­ ить, что дей­ств­ ие пос­ лед­ ов­ ат­ ель­нос­ ти пох­ ож­ е на вы­ход «quit». 4. По­мес­тить код troff для жир­ног­ о шрифт­ а во­круг слов­ а: :map v i\fB^[e\fP^[ Здесь предп­ ол­ аг­ а­ет­ся, что кур­сор стои­ т в нач­ а­ле сло­ва. Сна­ча­ла вы пер­ е­ход­ и­те в реж­ им вставк­ и, зат­ ем ввод­ и­те код для жир­но­го шриф­ та. Сле­ду­ет отм­ ет­ ить, что в ком­ ан­дах отоб­ раж­ е­ния не нужн­ о впис­ ы­ вать две обр­ ат­ные ко­сые чер­ты для по­луч­ ен­ ия одн­ ой. По­сле этог­ о пос­ ред­ст­вом ввод­ а «спрят­ ан­ног­ о» ESC про­исх­ од­ ит пер­ ех­ од в ко­манд­ ный реж­ им. На­ко­нец, к конц­ у сло­ва при­пис­ ыв­ ае­ тс­ я за­верш­ ающ­ ий код troff, по­сле че­го вы воз­вра­щае­тесь в ко­манд­ный реж­ им. Обр­ а­ти­ те вним­ ан­ ие, что при до­бавл­ ен­ ии ко­да к конц­ у слов­ а пос­ лед­ ов­ ат­ ель­ ность ea не нуж­на, так как она уже отоб­ ра­же­на на одн­ у бу­кв­ у e. Это пок­ аз­ ы­вае­ т, что отоб­ ра­женн­ ые пос­ лед­ ов­ а­тель­нос­ ти мог­ ут сод­ ер­жать друг­ ие отоб­ ра­жен­ ия (возм­ ожн­ ость ис­польз­ о­вать влож­ енн­ ые по­сле­ дов­ а­тельн­ ос­ ти ото­браж­ ен­ ий управл­ яе­ т­ся опц­ и­ей vi remap, ко­тор­ ая обыч­но вклю­чен­ а). 5. По­мес­тить вок­ руг слов­ а HTML-код жир­ног­ о шриф­та, даж­ е есл­ и кур­ сор рас­по­ло­жен не в нач­ ал­ е слов­ а: :map V lbi<B>^[e</B>^[ Эта пос­ лед­ о­ват­ ельн­ ость нап­ о­мин­ ае­ т пред­ ы­дущ­ ую: помимо тог­ о, что здесь при­сут­ст­вуе­ т HTML, а не troff, она исп­ ольз­ уе­ т lb для вы­полн­ е­ ния до­пол­ни­тельн­ ой задачи – пом­ е­ще­ния кур­со­ра в  на­чал­ о слов­ а. Ес­ли курс­ ор нах­ о­дит­ся в  се­ре­дин­ е сло­ва, то ком­ ан­да b пе­рем­ ест­ ит его на нач­ а­ло. Од­нак­ о ес­ли кур­сор уже на­хо­дитс­ я в на­ча­ле слов­ а, ко­ манд­ а b пер­ е­нес­ ет его на нач­ а­ло пре­дыд­ ущ­ ег­ о сло­ва. Чтоб­ ы иск­ лю­ чить эту воз­мож­ность, пер­ ед b стои­ т l. Мож­но опр­ е­дел­ ить вар­ иа­ н­ты этой пос­ лед­ ов­ ат­ ельн­ о­сти, за­ме­няя b на B и e на Ea. Во вся­ком слу­чае, ко­ман­да l по­меш­ ае­ т вы­пол­не­нию пос­ ле­до­ват­ ельн­ ос­ ти, есл­ и курс­ ор сто­ит в конц­ е стро­ки (это мож­но обойт­ и, доб­ а­вив про­бел).

Сохранение команд 1316. Най­ти и удал­ ить скоб­ки вок­ руг сло­ва или фра­зы1 по все­му до­ку­мент­ у: :map = xf)xn Здесь пред­пол­ аг­ а­ет­ся, что снач­ ал­ а ком­ анд­ ой /( вы най­де­те отк­ рыв­ а­ ю­щую скоб­ку, а за­тем наж­ мет­ е ENTER. Есл­ и нео­ б­хо­ди­мо удал­ ить скобк­ и, ис­польз­ уйт­ е ком­ ан­ду map сле­дую­ щим обр­ а­зом: уда­ли­те отк­ рыв­ ающ­ ую скоб­ку с пом­ о­щью x, най­дит­ е зак­ ры­ваю­щую с пом­ о­щью f), удал­ и­те ее с пом­ о­щью x и по­вто­ри­те по­ иск отк­ рыв­ ающ­ ей скоб­ки ко­ман­дой n. Есл­ и вы не хот­ и­те удал­ ять скобк­ и (нап­ рим­ ер, ког­ да они стоя­ т пра­ виль­но), не исп­ ольз­ уй­те ото­бра­жен­ную ко­ман­ду, а вмес­ то это­го на­ жмит­ е n для по­ис­ка нов­ ой от­крыв­ ающ­ ей скобк­ и. По­сле­дов­ ат­ ель­ность ото­браж­ ения из этог­ о при­мер­ а можн­ о изм­ е­нить так, что­бы она обр­ аб­ ат­ ыв­ ал­ а не скоб­ки, а ка­вычк­ и.7. Сде­лать всю строк­ у комм­ ен­та­ри­ем C/C++: :map g I/* ^[A */^[ Эта по­сле­дов­ а­тель­ность до­бавл­ я­ет соч­ е­тан­ ие /* в  нач­ а­ло стро­ки, а к конц­ у прип­ ис­ ыв­ ае­ т */. То же са­мое можн­ о сдел­ ать, ото­бра­зив ко­ ман­ду подс­ тан­ овк­ и: :map g :s;.*;/* & */;^M Здесь с по­мощ­ ью .* мы ищем соо­ тв­ етс­ тв­ ие всей стро­ке, за­тем при ее вос­прои­ зв­ е­ден­ ии (ис­поль­зуя &) пом­ ещ­ а­ем ее меж­ду симв­ ол­ ам­ и ком­ мент­ ар­ ия. Об­ра­тит­ е вни­ма­ние, что в ка­че­ств­ е разд­ е­лит­ е­лей исп­ оль­ зую­ тс­ я точк­ и с зап­ я­той, что­бы не при­шлось эк­ра­нир­ о­вать / в ком­ мент­ ар­ и­ях.8. Безо­ пасн­ о по­вто­рить боль­шую вставк­ у: :map ^J :set wm=0^M.:set wm=10^M Как уже гов­ о­рил­ ось в глав­ е 2, в vi ино­гда воз­ни­кае­ т про­бле­ма, свя­ зан­ная с пов­ то­рен­ ие­ м больш­ их вста­вок текс­ та при включ­ ен­ной опц­ ии wrapmargin. Ком­ ан­да map пом­ ож­ ет с этим спра­вить­ся. Она вре­мен­но от­ клю­ча­ет wrapmargin (ус­тан­ о­вив ее рав­ной нул­ ю), вып­ олн­ яе­ т ко­манд­ у пов­ то­рен­ ия, а зат­ ем восс­ тан­ авл­ ив­ а­ет знач­ ен­ ие опц­ ии. Обр­ ат­ и­те вни­ ман­ ие, что в этой по­след­ ов­ а­тель­нос­ ти ото­бра­же­ния при­сутс­ т­вую­ т од­ но­вре­менн­ о ко­ман­ды vi и ex.В  пре­дыд­ у­щем прим­ ер­ е, нес­ мотр­ я на то, что ^J явл­ я­етс­ я ко­манд­ ой vi(пер­ е­ме­ща­ет курс­ ор вниз на одн­ у строк­ у), эта клав­ иш­ а безо­ пасн­ о отоб-ражается, по­сколь­ку ее дей­ст­вие ана­лог­ ичн­ о ко­манд­ е j. Сущ­ ес­ т­ву­етмно­го кла­виш, ко­тор­ ые либ­ о вы­пол­няю­ т анал­ ог­ ичн­ ые дру­гим дейс­ т­вия, ли­бо ред­ко ис­поль­зую­ т­ся. Одн­ ак­ о все-так­ и след­ уе­ т озн­ а­ко­митьс­ яс ком­ анд­ а­ми vi, пе­ред тем как сме­ло ис­польз­ о­вать клав­ иш­ и в ка­че­ств­ еото­бра­жаем­ ых, от­ка­зы­вая­ сь тем са­мым от их обыч­ных знач­ е­ний.1 Взят­ о из стат­ ьи Вальт­ ер­ а Зинт­ца (Walter Zintz) в UNIX World, ап­рель 1990.

132 Глава 7. Продвинутое редактированиеОтображение клавиш в режиме вставки Как пра­ви­ло, отоб­ раж­ ен­ ия ра­бот­ аю­ т толь­ко в ко­мандн­ ом реж­ и­ме. Дей­ ст­ви­тель­но, в реж­ им­ е встав­ки кла­виш­ и име­ют свои обычн­ ые зна­чен­ ия и им нель­зя при­пи­сать ко­манд­ ы. Тем не ме­нее, ес­ли доб­ а­вить в ком­ ан­ ду map воск­ лиц­ ат­ ель­ный знак, то мож­но отм­ ен­ ить обыч­ное знач­ ен­ ие кла­виш­ и и сдел­ ать отоб­ раж­ е­ние в реж­ и­ме вставк­ и. Эта функ­ция пол­ ез­ на при раб­ от­ е в реж­ и­ме встав­ки, ког­ да нужн­ о быс­ тр­ о отт­ уд­ а выйт­ и, вы­ полн­ ить ком­ анд­ у и вер­нутьс­ я об­ратн­ о. Предп­ о­ло­жим, вы наб­ ра­ли слов­ о и за­бы­ли выд­ ел­ ить его курс­ ив­ ом (по­ мест­ ить в ка­выч­ки и т. п.). Мо­же­те за­дать отоб­ раж­ ен­ ие тип­ а: :map! + ^[bi<I>^[ea</I> Те­перь при вво­де + в конц­ е слов­ а оно выд­ е­лит­ся HTML-ко­дом курс­ и­ва. Сам знак плюс­ а в тек­сте не поя­ вит­ся. Опр­ е­дел­ ен­ная по­доб­ным об­ра­зом по­сле­до­ва­тельн­ ость вы­хо­дит из ре­жи­ ма вставк­ и (^[), воз­вращ­ а­ет кур­сор в  на­чал­ о сло­ва, вставл­ яе­ т перв­ ую часть код­ а (bi<I>), снов­ а вы­ход­ ит из реж­ им­ а встав­ки (^[) и дви­га­ет кур­ сор впер­ ед на ме­сто вставк­ и втор­ ой час­ти код­ а (ea</I>). Пос­ кольк­ у ото­ бра­жен­ная пос­ ле­до­ват­ ельн­ ость нач­ и­на­етс­ я и зак­ ан­чив­ ае­ т­ся в реж­ и­ме вставк­ и, пос­ ле так­ о­го выд­ ел­ ен­ ия сло­ва мож­но про­дол­жать ввод тек­ста. А  вот дру­гой при­мер: доп­ ус­тим, нужн­ о пос­ та­вить двое­то­чие в  конц­ е пред­ ыд­ ущ­ ей стро­ки. Это мо­жет сде­лать сле­дующ­ ая ото­браж­ ен­ная по­ след­ о­ва­тельн­ ость1: :map! % ^[kA:^[jA Теп­ ерь, вве­дя % в люб­ ом мес­те те­ку­щей стро­ки, вы прип­ иш­ и­те двое­то­ чие к конц­ у пред­ ы­ду­щей. Эта ко­ман­да вых­ о­дит в ко­манд­ный реж­ им, пер­ ем­ е­щае­ т курс­ ор вверх на стро­ку и до­бавл­ я­ет к ней двоет­ оч­ ие (^[kA:), за­тем сно­ва вых­ о­дит из реж­ и­ма встав­ки, пер­ е­мещ­ ае­ т кур­сор на стро­ку ниж­ е и вклю­ча­ет реж­ им встав­ки (^[jA). Обр­ а­тит­ е вним­ ан­ ие, что в пре­дыд­ у­щих ко­манд­ ах ото­бра­жен­ ия мы ис­ польз­ о­вал­ и редк­ о встреч­ аю­щие­ся симв­ о­лы (% и +). Ес­ли симв­ ол отоб­ ра­ жен для реж­ им­ а встав­ки, вы уже не смож­ ет­ е ввод­ ить его как текст. Что­бы верн­ уть знак­ у его прям­ ое зна­че­ние, ис­польз­ уй­те ко­манд­ у: :unmap! x где x – это симв­ ол, ко­тор­ ый пре­ж­де был ото­браж­ ен для ре­жим­ а встав­ки (хо­тя vi рас­кро­ет симв­ ол x в ко­манд­ной стро­ке при его ввод­ е, и это бу­дет пох­ о­же на сня­тие отоб­ ра­же­ния раск­ ры­то­го тек­ста, он прои­ з­ве­дет кор­ рект­ную от­ме­ну отоб­ ра­же­ния симв­ о­ла). Ото­бра­жен­ ия в  реж­ им­ е встав­ки боль­ше под­ход­ ят для при­вяз­ки сим­ вольн­ ых строк к спе­циа­ льн­ ым кла­ви­шам, не ис­польз­ уе­мым для дру­гих 1 Из стат­ ьи Walter Zintz в журнале UNIX World, апрель 1990.

Сохранение команд 133 це­лей. Оно особ­ енн­ о пол­ ез­но при раб­ о­те с про­грамм­ ир­ уе­мы­ми функ­цио­ нальн­ ым­ и клав­ иш­ ам­ и.Отображения функциональных клавиш Мно­гие тер­мин­ ал­ ы име­ют прог­ рамм­ и­руе­мые функц­ ион­ альн­ ые клав­ и­ ши1 (кот­ о­рые удачн­ о эму­лир­ у­ют­ся на эмул­ я­тор­ ах терм­ ин­ а­лов на со­вре­ мен­ных раст­ ров­ ых ра­боч­ их станц­ и­ях). В  спец­ и­альн­ ом уст­ а­нов­ оч­ном реж­ им­ е (setup) тер­мин­ ал­ а эти кла­виш­ и мож­но нас­ трои­ ть на пе­чать од­ ног­ о или не­сколь­ких лю­бых симв­ о­лов. Одн­ а­ко клав­ иш­ и, за­про­грам­ми­ ров­ ан­ные в уст­ ан­ ов­ оч­ном реж­ им­ е тер­мин­ а­ла, бу­дут ра­бо­тать толь­ко на этом терм­ ин­ ал­ е. Кром­ е тог­ о, при этом ог­ра­ни­чив­ а­ютс­ я дей­ств­ ия про­ грамм, ис­польз­ ую­щих функ­цион­ аль­ные клав­ иш­ и в сво­их цел­ ях. ex поз­ вол­ яе­ т ото­бра­зить эти кла­виш­ и в вид­ е чис­ ел с по­мощ­ ью: :map #1 commands для функ­цио­наль­ной клав­ иш­ и ном­ ер 1 и так дал­ ее (это возм­ ожн­ о, по­то­ му что ред­ ак­тор име­ет дост­ уп к той за­пис­ и в ба­зах данн­ ых terminfo или termcap, где есть ин­форм­ ац­ ия об обн­ а­руж­ ен­ном тер­мин­ а­ле, и знае­ т, ка­ кая Escape-по­след­ о­ва­тельн­ ость обычн­ о со­отв­ етс­ т­вуе­ т опр­ ед­ е­лен­ной функ­цио­наль­ной клав­ иш­ е). Как и в случ­ ае обыч­ных кно­пок, по умол­ча­нию отоб­ ра­жен­ ия от­нос­ ят­ся к  ком­ андн­ о­му реж­ им­ у, но с помощью ко­ман­ды map! функ­цион­ аль­ной клав­ иш­ е можн­ о за­дать два разл­ ичн­ ых зна­чен­ ия: од­но для ко­мандн­ ог­ о реж­ и­ма, а другое – для реж­ им­ а вставк­ и. На­при­мер, при вер­ст­ке HTML можн­ о прис­ во­ить функ­цио­нальн­ ым клав­ иш­ ам ко­ды изм­ е­не­ния на­чер­ та­ния шриф­та: :map #1 i<I>^[ :map! #1 <I> Ес­ли вы нах­ од­ ит­ есь в ком­ анд­ном реж­ им­ е, то перв­ ая функц­ ио­наль­ная кла­виш­ а пер­ ев­ е­дет вас в реж­ им вставк­ и, вве­дет симв­ ол­ ы <I> и верн­ ет в ко­мандн­ ый реж­ им. Есл­ и польз­ о­ва­тель уже нах­ о­дит­ся в реж­ и­ме встав­ ки, клав­ иш­ а про­сто до­ба­вит HTML-код из трех симв­ о­лов. Ес­ли по­след­ ов­ а­тельн­ ость со­держ­ ит ^M ( возв­ рат ка­ретк­ и), то наж­ ми­те CTRL-M. На­при­мер, что­бы функ­цио­нальн­ ая кла­виш­ а 1 бы­ла дост­ уп­на для отоб­ ра­жен­ ия, зап­ ись в тер­мин­ аль­ной ба­зе данн­ ых для ва­шег­ о тер­ мин­ ал­ а долж­на со­держ­ ать прим­ ер­но след­ ующ­ ее опр­ е­де­лен­ ие для k1: k1=^A@^M В свою оче­редь, оп­ред­ ел­ е­ние: ^A@^M долж­но по­явл­ ятьс­ я в выв­ од­ е при наж­ а­тии этой кноп­ки. 1 На сов­ ре­менн­ ой кла­виат­ у­ре PC им со­отв­ етс­ т­вую­ т функ­цио­нальн­ ые кла­ви­ ши F1–F12. – Прим. нау­ ч. ред.

134 Глава 7. Продвинутое редактирование Что­бы увид­ еть зна­чен­ ие функ­цион­ аль­ной клав­ иш­ и, вос­польз­ уйт­ есь ко­манд­ ой od (octal dump) с опц­ ие­ й -c (по­каз­ ы­вать каж­дый симв­ ол). Те­ перь по­сле наж­ ат­ ия этой функц­ ио­нальн­ ой кла­виш­ и вве­ди­те ENTER, а зат­ ем CTRL-D, чтоб­ ы ком­ анд­ а od вы­ве­ла ин­форм­ ац­ ию. На­при­мер: $ od -c ^[[[A ^D 0000000 033 [ [ A \n 0000005 Здесь функц­ ио­нальн­ ая клав­ иш­ а пос­ ы­лае­ т компьютеру Escape, две ле­ вых квадр­ ат­ных скобк­ и и A.Отображения для других специальных клавиш Мног­ ие кла­виат­ ур­ ы сод­ ерж­ ат спе­циа­ ль­ные кнопк­ и, дубл­ ир­ ующ­ ие ко­ манд­ ы vi, так­ ие как HOME, END, PAGE UP и PAGE DOWN. Ес­ли опи­са­ ние тер­мин­ а­ла в terminfo или termcap яв­ляе­ тс­ я пол­ным, то vi смо­жет рас­ по­знать эти кла­ви­ши. Одн­ а­ко есл­ и это не так, то можн­ о ис­поль­зо­вать ко­ман­ду map, что­бы сде­лать их дост­ упн­ ым­ и в  vi. Обычн­ о эти кла­ви­ши по­сы­ла­ют комп­ ь­ют­ ер­ у Escape-последовательность – симв­ ол Es­cap­ e, за ко­тор­ ым след­ уе­ т строк­ а из од­ног­ о или нес­ коль­ких симв­ о­лов. Чтоб­ ы пре­дот­врат­ ить обр­ аб­ от­ку Escape в ex, нуж­но наж­ ать ^V пе­ред спе­циа­ ль­ ной клав­ иш­ ей в ком­ ан­де ото­браж­ е­ния. Нап­ рим­ ер, чтоб­ ы кнопк­ е HOME на кла­виа­ту­ре IBM PC по­ста­вить в  со­от­ветс­ тв­ ие подх­ о­дя­щий эк­вив­ а­ лент из vi, мож­но опр­ ед­ е­лить сле­дующ­ ее отоб­ ра­же­ние1: :map CTRL-V HOME 1G На эк­ран­ е это бу­дет выг­ ляд­ еть так: :map ^[[H 1G По­хож­ ие ко­манд­ ы ото­браж­ ен­ ия выг­ ляд­ ят след­ ую­щим об­ра­зом: :map CTRL-V END G по­ка­жет :map ^[[Y G :map CTRL-V PAGE UP ^F по­каж­ ет :map ^[[V ^F :map CTRL-V PAGE DOWN ^B по­ка­жет :map ^[[U ^B Воз­мож­но, вам зах­ о­чет­ся по­мес­тить эти ото­браж­ ен­ ия в файл .exrc. Об­ ра­ти­те вним­ ан­ ие, что ес­ли спец­ и­альн­ ая кла­виш­ а вы­раб­ ат­ ы­вае­ т длин­ ную экр­ ан­ и­рующ­ ую пос­ ле­дов­ а­тель­ность (со­дер­жащ­ ую нес­ коль­ко неп­ е­ ча­тае­мых симв­ ол­ ов), ^V защ­ и­тит от ин­терп­ ре­тац­ ии тольк­ о пер­вый Es­ca­ pe-симв­ ол, и ото­браж­ ен­ ие не бу­дет ра­бот­ ать. Вме­сто то­го чтоб­ ы прос­ то наж­ и­мать ^V, а за­тем нужн­ ую кла­виш­ у, вам при­дет­ся отыс­ кать полн­ ую Escape-по­след­ ов­ а­тель­ность (воз­мож­но, в ру­ко­вод­ стве по ва­шем­ у тер­ми­ на­лу) и  вве­сти ее вручн­ ую, исп­ оль­зуя ^V там, где это не­об­хо­ди­мо для защ­ и­ты Escape-симв­ о­лов от ин­тер­пре­тац­ ии. 1 Скор­ ее след­ о­вал­ о бы на­пис­ ать :map ^[[H ^, поскольку авт­ орс­ кий ва­риа­ нт ко­ манд­ ы пер­ ен­ ос­ ит кур­сор в нач­ ал­ о фай­ла, а не стро­ки. – Прим. нау­ ч. ред.

Сохранение команд 135 Есл­ и вы польз­ уе­тесь раз­личн­ ым­ и ти­пам­ и тер­ми­на­лов (на­прим­ ер, конс­ о­ лью на PC и xterm), то не на­до ожид­ ать, что ото­браж­ ен­ ия, по­доб­ные пред­ став­лен­ным вы­ше, всег­ да буд­ ут раб­ о­тать. Для та­ких слу­чае­ в Vim пре­дос­ тав­ля­ет пе­рен­ о­сим­ ый спо­соб для опи­сан­ ия та­ких отоб­ раж­ ен­ ий клав­ иш: :map <Home> 1G Вве­ди­те шесть симв­ ол­ ов: < H o m e > (Vim)Отображение нескольких клавиш ввода Отоб­ раж­ е­ние наж­ ат­ ий на нес­ коль­ко кла­виш не ог­ран­ и­чи­вае­ тс­ я функ­ цио­нальн­ ы­ми кнопк­ ам­ и. Можн­ о так­же отоб­ ра­жать по­сле­дов­ а­тель­но­ сти на­жат­ ий обычн­ ых клав­ иш. Это пом­ ож­ ет при ввод­ е оп­ред­ ел­ ен­ных тип­ ов текс­ та, нап­ рим­ ер XML или HTML. Опир­ а­ясь на Джер­ри Пик­ а (Jerry Peek), соа­ вт­ ор­ а из­дан­ной O’Reilly кни­ ги Learning the Unix Operating System, при­вод­ им нек­ о­тор­ ые из ко­манд :map, об­легч­ ающ­ ие ввод раз­мет­ки XML. (Стро­ки, на­чин­ аю­щие­ся с двой­ ной кав­ ыч­ки, явл­ я­ютс­ я комм­ ен­та­риям­ и. Поз­же об этом бу­дет расс­ ка­ за­но в раз­дел­ е «Комм­ ент­ а­рии в скрип­тах ex» на стр. 142.) \" ADR: need this :set noremap \" bold: map! =b </emphasis>^[F<i<emphasis role=\"bold\"> map =B i<emphasis role=\"bold\">^[ map =b a</emphasis>^[ \" Move to end of next tag: map! =e ^[f>a map =e f> \" footnote (tacks opening tag directly after cursor in text-input mode): map! =f <footnote>^M<para>^M</para>^M</footnote>^[kO \" Italics (\"emphasis\"): map! =i </emphasis>^[F<i<emphasis> map =I i<emphasis>^[ map =i a</emphasis>^[ \" paragraphs: map! =p ^[jo<para>^M</para>^[O map =P O<para>^[ map =p o</para>^[ \" less-than: map! *l &lt; ... Ес­ли поль­зо­ватьс­ я этим­ и ко­ман­да­ми, то для вво­да сно­ски вам нужн­ о пе­ рейт­ и в реж­ им встав­ки и на­брать =f. При этом vi по­ста­вит от­крыв­ ающ­ ие и за­кры­вающ­ ие те­ги и пом­ ес­тит кур­сор меж­ду ним­ и в реж­ и­ме вставк­ и: All the world's a stage.<footnote> <para> </para> </footnote>

136 Глава 7. Продвинутое редактирование Сто­ит ли гов­ о­рить, что при ра­бо­те над книг­ ой по­добн­ ые макр­ ос­ ы ока­за­ лись чрез­выч­ айн­ о пол­ езн­ ы.@-функции Име­нов­ анн­ ые бу­фер­ ы пред­ ос­тав­ляю­ т еще один спос­ об соз­дан­ ия «мак­ рос­ ов» – сложн­ ых по­след­ о­ват­ ель­нос­ тей ко­манд, кот­ ор­ ые мож­но вып­ ол­ нять всег­ о нес­ коль­ким­ и наж­ ат­ ия­ми клав­ иш. Ес­ли в текс­ те нап­ ис­ ать ко­манд­ у (это мо­жет быть пос­ ле­до­ва­тель­ность vi или ком­ анд­ а ex, пе­ред ко­то­рой сто­ит двое­точ­ ие), а зат­ ем уда­лить ее в  име­нов­ ан­ный буф­ ер, то сод­ ер­жим­ ое этог­ о буф­ ер­ а можн­ о вы­пол­нить с по­мощ­ ью ко­ман­ды @. Нап­ рим­ ер, в но­вой стро­ке введ­ ит­ е сле­дующ­ ее: cwgadfly CTRL-V ESC На эк­ра­не это бу­дет выг­ ля­деть так: cwgadfly^[ Снов­ а на­жми­те ESC для вы­хо­да из реж­ им­ а встав­ки и  удал­ и­те стро­ку в буф­ ер g, вве­дя \"gdd. Те­перь вся­кий раз при пом­ ещ­ ен­ ии кур­со­ра в на­ча­ ло сло­ва и ввод­ е @g это слов­ о бу­дет зам­ е­не­но на gadfly. По­сколь­ку @ ин­тер­пре­тир­ у­ет­ся как ко­ман­да vi, точ­ка (.) по­вто­рит всю по­след­ ов­ ат­ ельн­ ость, да­же есл­ и в бу­фер­ е со­держ­ итс­ я ко­ман­да ex. Со­че­ тан­ ие @@ по­втор­ ит пос­ ледн­ юю @, а u или U можн­ о исп­ оль­зо­вать для отм­ е­ ны дейс­ тв­ ия @. Это был про­стой при­мер. @-функц­ ии пол­ ез­ны, по­сколь­ку их можн­ о при­мен­ ять для са­мых не­обычн­ ых ком­ анд. Особ­ ен­но это удобн­ о при од­ но­врем­ енн­ ом ред­ акт­ и­ро­ва­нии нес­ кольк­ их файл­ ов, так как ком­ ан­ды со­ держ­ атс­ я в свои­ х име­но­ван­ных буф­ е­рах и их можн­ о вы­зы­вать из люб­ о­ го ре­дакт­ ир­ уем­ о­го файл­ а. @-функ­ции так­же по­лезн­ ы в со­че­тан­ ии с ко­ манд­ а­ми глоб­ аль­ной за­ме­ны, про кот­ ор­ ые расс­ ка­зы­ва­лось в гла­ве 6.Выполнение содержимого буферов в ex В  реж­ и­ме ex такж­ е мож­но вы­полн­ ить текст, со­хра­нен­ный в  буф­ ер­ е. В  этом слу­чае не­обх­ о­дим­ о вве­сти ко­манд­ у ex, удал­ ить ее в  имен­ ов­ ан­ ный бу­фер, пос­ ле чег­ о ис­польз­ ов­ ать ко­ман­ду @ из при­гла­ше­ния с двое­ то­чие­ м. Нап­ рим­ ер, введ­ ем сле­дую­щие строк­ и: ORA publishes great books. ORA is my favorite publisher. 1,$s/ORA/O'Reilly Media/g По­мест­ ив курс­ ор в  по­след­нюю строк­ у, уда­лит­ е ее в  буф­ ер g ко­ман­дой \"gdd, за­тем пос­ тавь­те кур­сор на пер­вую стро­ку (kk) и вы­полн­ и­те сод­ ер­ жащ­ ие­ся в  бу­фе­ре ком­ анд­ ы из ко­манд­ной строк­ и с  двое­то­чие­ м (:@g ENTER). На экр­ ан­ е вы долж­ны увид­ еть сле­дующ­ ее:

Использование скриптов ex 137 O'Reilly Media publishes great books. O'Reilly Media is my favorite publisher. В не­кот­ ор­ ых вер­си­ях vi симв­ ол * в ко­манд­ной стро­ке ex трак­туе­ т­ся так же, как и @. Кро­ме тог­ о, есл­ и по­сле ком­ анд @ или * стои­ т *, то ком­ анд­ а бер­ етс­ я из бу­фе­ра (неи­ ме­но­ванн­ о­го) по умол­ча­нию.Использование скриптов ex От­дель­ные ко­манд­ ы ex, так­ ие как ото­браж­ е­ния, аб­брев­ иа­ту­ры и проч­ ие, можн­ о исп­ ольз­ о­вать тольк­ о из vi. Есл­ и эти ком­ анд­ ы сох­ ран­ ить в фай­ле .exrc, они бу­дут авт­ ом­ ат­ и­чес­ ки вы­пол­нять­ся при за­пуск­ е ред­ ак­тор­ а. Файл, со­дер­жащ­ ий вып­ ол­няем­ ые ко­манд­ ы, наз­ ы­ва­етс­ я скрип­том. Ко­манд­ ы, сод­ ерж­ а­щие­ся в обычн­ ом скрип­те .exrc, нельз­ я ис­поль­зов­ ать вне vi, но мож­но со­хран­ ять в скрипт дру­гие ком­ ан­ды ex, а за­тем при­ме­ нять его к одн­ о­му или нес­ кольк­ им файл­ ам. Во внеш­них скрипт­ ах в ос­ нов­ном ис­польз­ ую­ тс­ я ко­манд­ ы под­стан­ ов­ки. При созд­ а­нии текс­ тов­ ых фай­лов скрип­ты ex мо­гут ис­поль­зов­ ать­ся при пров­ ер­ке прав­ иль­но­сти ис­польз­ уе­мых терм­ ин­ ов и да­же ор­фог­ ра­фии по всем­ у на­бор­ у док­ у­мент­ ов. Пред­по­лож­ им, вы вы­пол­ни­ли UNIX-ком­ ан­ ду spell с дву­мя файл­ ам­ и, и она вы­да­ла сле­дующ­ ий спис­ ок опеч­ а­ток: $ spell sect1 sect2 chmod ditroff myfile thier writeable Как час­то бы­вае­ т, про­верк­ а орф­ о­граф­ ии выя­ вил­ а не­сколь­ко тех­нич­ е­ ских тер­мин­ ов и спец­ и­альн­ ых случ­ а­ев, ко­то­рые не смог­ла расп­ о­знать. Од­нак­ о она на­шла и две нас­ тоя­щих ошибк­ и в нап­ и­сан­ ии. По­сколь­ку мы про­вер­ ил­ и два файл­ а сраз­ у, нам не­изв­ ест­но, в как­ ом из них со­держ­ атс­ я эти ошиб­ки и где они рас­по­ло­же­ны. Хот­ я есть спо­соб­ ы их опр­ е­дел­ ить, да и для двух ошиб­ ок в двух файл­ ах та­кая зад­ а­ча не­об­ рем­ е­ни­тель­на, но легк­ о предс­ та­вить, на­скольк­ о воз­раст­ ет объ­ем ра­бо­ ты у бедн­ ог­ о корр­ ект­ ор­ а или наб­ орщ­ ик­ а при про­верк­ е больш­ о­го кол­ и­ че­ст­ва фай­лов. Что­бы обл­ ег­чить за­дач­ у, мож­но нап­ ис­ ать скрипт ex со сле­дую­щим­ и ко­ ман­дам­ и: %s/thier/their/g %s/writeable/writable/g wq Пусть мы сох­ ра­нил­ и эти стро­ки в файл exscript. Этот скрипт мож­но за­ пус­тить из vi с по­мощ­ ью ко­манд­ ы: :so exscript

138 Глава 7. Продвинутое редактирование Его так­же мож­но при­мен­ ить к файл­ у прям­ о в ком­ андн­ ой строк­ е и отр­ е­ дакт­ ир­ о­вать файл­ ы sect1 и sect2 след­ ующ­ им обр­ аз­ ом: $ ex -s sect1 < exscript $ ex -s sect2 < exscript Ключ -s, след­ ующ­ ий за выз­ ов­ ом ex, – это POSIX-спо­соб прик­ а­зать ре­ дакт­ ор­ у под­ ав­лять обыч­ный выв­ од на терм­ ин­ ал1. Есл­ и бы скрипт был боль­ше, чем в этом прос­ том при­мер­ е, то мы бы уже сэкон­ ом­ ил­ и нек­ о­то­рое вре­мя. Одн­ ак­ о вы мо­жет­ е спро­сить, можн­ о ли как-то изб­ еж­ ать по­вто­рен­ ия это­го проц­ есс­ а для каж­дог­ о из ред­ акт­ и­ руем­ ых файл­ ов. Кон­ ечн­ о да, мы мож­ ем на­пис­ ать скрипт обол­ очк­ и, ко­ тор­ ый не тольк­ о вклю­ча­ет, но и обобщ­ ае­ т вы­зов ex, так что его мож­но ис­польз­ о­вать для люб­ о­го числ­ а фай­лов.Циклы в скриптах командной строки Вы, нав­ ер­ное, уже знае­те, что обо­лоч­ка – это не толь­ко ин­тер­пре­тат­ ор ко­манд­ной строк­ и, но и  язык прог­ рамм­ ир­ ов­ ан­ ия. Что­бы выз­ вать ex с  нес­ коль­ким­ и фай­ла­ми, мы исп­ ольз­ уе­ м про­стую ком­ анд­ у обо­лочк­ и, наз­ ы­вае­мую цик­лом for. Он по­звол­ яе­ т вы­пол­нять пос­ лед­ ов­ а­тель­ность ком­ анд для каж­дог­ о арг­ ум­ ент­ а скрип­та. (Возм­ ожн­ о, цикл for яв­ля­ет­ся наи­бол­ ее час­то исп­ оль­зуем­ ым кус­ком код­ а для нач­ и­наю­щих осв­ аив­ ать прог­ рамм­ ир­ ов­ а­ние в обо­лочк­ е. Его сто­ит нау­ чить­ся ис­польз­ ов­ ать, да­ же есл­ и вы не со­би­рае­тесь пис­ ать дру­гие скрипт­ ы.) Цикл for име­ет след­ ующ­ ий синт­ ак­сис: for variable in list do command(s) done На­при­мер: for file in $* do ex - $file < exscript done (От­ступ в ко­ман­де можн­ о не де­лать; у нас он пок­ аз­ ан для удоб­ств­ а чте­ ния.) По­сле соз­да­ния этог­ о скрип­та со­хран­ им его в  фай­ле с  имен­ ем correct и сдел­ а­ем его исп­ ол­няе­мым ком­ ан­дой chmod (есл­ и вы не знак­ ом­ ы с ко­ман­дой chmod и дейс­ т­вия­ми, нео­ бх­ о­дим­ ы­ми для ее поп­ а­да­ния в пу­ ти пои­ с­ка UNIX, по­чит­ ай­те книг­ у Learning the UNIX Operating System, опуб­лик­ ов­ ан­ную в O’Reilly). Те­перь введ­ ем: $ correct sect1 sect2 1 Обычн­ о для этой цел­ и ex ис­польз­ уе­ т один­ оч­ный знак мин­ ус­ а. Для обр­ ат­ной со­вмес­тим­ о­сти под­держ­ ив­ аю­ т­ся оба спо­со­ба.

Использование скриптов ex 139Цикл for в  correct при­сво­ит пер­ ем­ енн­ ой file кажд­ ый арг­ ум­ ент (каж­дый файл в спи­ске, опр­ ед­ е­лен­ном как $*, что озн­ а­ча­ет все арг­ ум­ ент­ ы)и вып­ олн­ ит скрипт ex с со­дер­жим­ ым каж­дой из этих пе­ре­мен­ных.Пон­ ять принц­ ип ра­бо­ты цикл­ ов for буд­ ет про­ще, ес­ли взять прим­ ерс бо­лее оче­вид­ным вы­вод­ ом. Пос­ мот­рим на скрипт для пер­ еи­ мен­ ов­ ан­ ияфай­лов:for file in $*do mv $file $file.xdoneПредп­ ол­ о­жим, что этот скрипт рас­пол­ ож­ ен в исп­ ол­няем­ ом файл­ е с име­нем move. Мы мо­жем сде­лать след­ ующ­ ее:$ ls Толь­ко фай­лы глав (ch...)ch01 ch02 ch03 move Пров­ е­рим ре­зуль­тат­ ы$ move ch??$ lsch01.x ch02.x ch03.x moveЕсл­ и под­ ойт­ и к дел­ у твор­чес­ ки, то можн­ о по-друг­ ом­ у пер­ еп­ и­сать скрипт,пе­ре­имен­ ов­ ыв­ аю­щий фай­лы:for nn in $*do mv ch$nn sect$nndoneВ так­ ом скрип­те сле­ду­ет ука­зы­вать в ко­мандн­ ой строк­ е не имен­ а, а но­мер­ а файл­ ов:$ lsch01 ch02 ch03 move$ move 01 02 03$ lssect01 sect02 sect03 moveЦик­лу for не обяз­ а­тельн­ о треб­ у­ет­ся $* (с люб­ ы­ми ар­гум­ ент­ а­ми) в ка­че­ст­ве спи­ска знач­ ен­ ий. Мож­но указ­ ать спи­сок в явн­ ом ви­де. На­при­мер:for variable in a b c dприс­ ваи­ва­ет variable знач­ е­ния a, b, c и d по оче­ре­ди. Такж­ е мож­но под­ставл­ ять выв­ од дру­гой ком­ анд­ ы.На­при­мер:for variable in `grep -l \"Alcuin\" *`при­сво­ит variable по оче­ред­ и имя каж­до­го фай­ла, в кот­ ор­ ом grep найд­ етстрок­ у Alcuin. (grep -l вы­вод­ ит имен­ а тех фай­лов, сод­ ер­жим­ ое кот­ о­рыхотв­ еч­ а­ет шабл­ он­ у, без выв­ о­да сам­ их строк, где есть совп­ а­ден­ ие.)Есл­ и спис­ ок не ука­зан:for variable

140 Глава 7. Продвинутое редактирование пер­ ем­ ен­ной variable бу­дет при­свое­ н кажд­ ый из ар­гу­мен­тов ко­манд­ной стро­ки, как был­ о в наш­ ем пер­вом при­мер­ е. Во­общ­ е го­вор­ я, это равн­ о­ сильн­ о не так­ ой ком­ анд­ е: for variable in $* а так­ ой: for variable in \"$@\" Пос­ лед­нее вы­ра­же­ние име­ет нем­ но­го дру­гое зна­чен­ ие. Симв­ ол $* рас­ крыв­ а­етс­ я в $1, $2, $3 и т. д., а по­сле­до­ва­тель­ность из че­ты­рех симв­ о­лов \"$@\" – в \"$1\", \"$2\", \"$3\" и т. д. Кав­ ыч­ки защ­ ищ­ а­ют от по­след­ ующ­ ей инт­ ер­ прет­ а­ции спец­ и­альн­ ых симв­ ол­ ов1. Да­вайт­ е верн­ ем­ся к ос­новн­ ой идее и наш­ ем­ у пер­вон­ ач­ аль­но­му скрип­ту: for file in $* do ex - $file < exscript done Ис­польз­ о­ван­ ие двух скриптов – скрипт­ а обо­лочк­ и и ком­ ан­ды ex – мо­ жет по­каз­ ать­ся нем­ но­го без­вкус­ным. Ведь факт­ и­чес­ ки обо­лочк­ а са­ма да­ет спо­соб вклю­чить скрипт ред­ ак­тир­ ов­ а­ния в скрипт обо­лочк­ и.Документы heredoc В скрип­тах обо­лоч­ки опе­рат­ ор << оз­на­ча­ет взять в ка­чес­ т­ве вво­да ко­ман­ ды след­ ующ­ ие да­лее стро­ки вплоть до указ­ анн­ ог­ о марк­ ер­ а. (Част­ о это на­зы­ваю­ т док­ у­мен­том heredoc.) С  пом­ ощ­ ью это­го син­так­сис­ а мы мо­ жем вклю­чить в correct соб­ст­вен­ные ком­ ан­ды ре­дак­тир­ о­ва­ния сле­дую­ щим обр­ аз­ ом: for file in $* do ex - $file << end-of-script g/thier/s//their/g g/writeable/s//writable/g wq end-of-script done Стро­ка-марк­ ер end-of-script со­вер­шенн­ о прои­ зв­ ол­ ен. Единс­ т­вен­ное тре­ бо­ва­ние сос­ то­ит в том, что это дол­жен быть на­бор симв­ ол­ ов, не сод­ ерж­ а­ щихс­ я во ввод­ е, чтоб­ ы обо­лоч­ка могл­ а рас­поз­ нать кон­ ец до­ку­мен­та heredoc. Такж­ е его нуж­но пом­ ес­тить на нач­ а­ло стро­ки. По сог­ ла­ше­нию мног­ ие польз­ о­ват­ ел­ и ука­зы­ва­ют кон­ ец до­ку­мен­та heredoc стро­кой EOF или E_O_F, обоз­ на­чаю­щей ко­нец фай­ла. 1 На­при­мер, есл­ и знач­ ен­ ие ка­кой-ли­бо из пер­ ем­ ен­ных $1, $2, $3 (имя фай­ла- арг­ у­мент­ а в прим­ ер­ е выш­ е) сод­ ер­жит про­бел, то в цик­ле по \"$@\" оно буд­ ет пред­ставл­ е­но одн­ им значением (что пра­виль­но), а в цикл­ е по $* – нес­ коль­ ки­ми раз­ны­ми знач­ е­ниям­ и (что не­пра­вильн­ о). – Прим. на­уч. ред.

Использование скриптов ex 141 Каж­дый из предс­ тав­лен­ных спос­ об­ ов име­ет свои дост­ о­ин­ст­ва и не­дос­ тат­ки. Есл­ и вы хот­ ит­ е про­дел­ ать сер­ ию од­нок­ рат­ных прав­ ок и го­то­вы пер­ еп­ и­сы­вать скрипт кажд­ ый раз, то док­ у­мент heredoc дае­ т эф­фект­ ив­ ное ре­ше­ние этой зад­ ач­ и. Одн­ а­ко бол­ ее гибк­ ий спо­соб со­сто­ит в за­пис­ и ком­ анд ре­дакт­ ир­ ов­ ан­ ия в от­дель­ном от скрип­та обол­ оч­ки файл­ е. На­прим­ ер, мож­но дог­ о­вор­ ить­ ся, что вы всег­ да разм­ е­щае­те ко­ман­ды ре­дакт­ ир­ ов­ а­ния в фай­ле с име­ нем exscript. В этом слу­чае скрипт correct нужн­ о нап­ ис­ ать все­го один раз. Его мож­но хран­ ить в спец­ иа­ льн­ ом «утил­ итн­ ом» ка­та­ло­ге (кот­ ор­ ый сод­ ер­жит­ся в пу­ти пои­ ск­ а) и ис­польз­ ов­ ать в люб­ ое вре­мя.Сортировка текстовых блоков: пример скрипта ex Предп­ о­лож­ им, вам нуж­но рас­по­ло­жить в ал­фав­ итн­ ом по­ряд­ке оп­ред­ е­ ле­ния глосс­ а­рия, со­держ­ ащ­ иес­ я в  раз­ме­чен­ном troff-фай­ле. Кажд­ ый терм­ ин нач­ ин­ а­етс­ я с  мак­ро­са .IP. Вдо­ба­вок, каж­дый пункт за­клю­чен в пар­ е мак­рос­ ов .KS/.KE (чтоб­ ы каж­дый тер­мин выс­ туп­ ал в бло­ке со сво­ им опр­ е­дел­ е­ни­ем, то есть что­бы они не оказ­ а­лись на раз­ных стран­ и­ цах). Файл глос­са­рия име­ет прим­ ерн­ о след­ ую­щий вид: .KS .IP \"TTY_ARGV\" 2n The command, specified as an argument vector, that the TTY subwindow executes. .KE .KS .IP \"ICON_IMAGE\" 2n Sets or gets the remote image for icon's image. .KE .KS .IP \"XV_LABEL\" 2n Specifies a frame's header or an icon's label. .KE .KS .IP \"SERVER_SYNC\" 2n Synchronizes with the server once. Does not set synchronous mode. .KE Ес­ли про­гнать его строк­ и чер­ ез UNIX-ком­ ан­ду sort, то мож­но прив­ ест­ и файл в  алф­ а­витн­ ый по­ря­док. Од­нак­ о нам не нуж­но сор­тир­ о­вать все стро­ки под­ряд. От­сор­тир­ о­ва­ны долж­ны быть тольк­ о терм­ ин­ ы глос­са­ рия, а кажд­ ое оп­ре­дел­ е­ние долж­но ост­ ать­ся нет­ рон­ ут­ ым и след­ ов­ ать за соо­ тв­ етс­ тв­ ующ­ им тер­мин­ ом. Ока­зы­вае­ т­ся, каж­дый тек­стов­ ый блок можн­ о рас­сматр­ ив­ ать как це­лое, есл­ и объ­еди­нить блок в од­ной стро­ке. Вот перв­ ая верс­ ия на­шег­ о скрип­та ex: g/^\.KS/,/^\.KE/j %!sort

142 Глава 7. Продвинутое редактирование Каж­дый пункт глосс­ а­рия расп­ о­ло­жен меж­ду макр­ о­са­ми .KS и .KE. Ко­ манд­ а ex j объе­ дин­ яе­ т строк­ и (ее экв­ ив­ ал­ ент в vi наз­ ы­ва­етс­ я J), поэ­ том­ у перв­ ая ко­ман­да объе­ дин­ яе­ т кажд­ ую за­пись глос­сар­ ия в од­ну «строк­ у». След­ ую­щая ком­ анд­ а от­сор­ти­ру­ет файл, и на вы­хо­де пол­ у­читс­ я что-то врод­ е это­го: .KS .IP \"ICON_IMAGE\" 2n Sets or gets ... image. .KE .KS .IP \"SERVER_SYNC\" 2n Synchronizes with ... mode. .KE .KS .IP \"TTY_ARGV\" 2n The command, ... executes. .KE .KS .IP \"XV_LABEL\" 2n Specifies a ... icon's label. .KE Сей­час строк­ и от­сорт­ ир­ о­ва­ны по зап­ ис­ ям. К  сож­ а­лен­ ию, макр­ ос­ ы и текст в них пе­ре­меш­ ал­ ись (мног­ от­ оч­ ия […] обо­зна­чаю­ т проп­ ущ­ ен­ный текст). Те­перь над­ о как-то встав­ ить пер­ е­но­сы, чтоб­ ы «разъ­ед­ ин­ ить» стро­ки. Это мож­но сдел­ ать, изм­ е­нив скрипт ex след­ ую­щим обр­ аз­ ом: пе­ ред объе­ ди­нен­ и­ем нужн­ о по­ме­тить точк­ и объ­еди­не­ния, а  за­тем за­ме­ нить эти метк­ и на пе­ре­вод стро­ки. Расш­ и­рен­ный скрипт ex имее­ т вид: g/^\.KS/,/^\.KE/-1s/$/@@/ g/^\.KS/,/^\.KE/j %!sort %s/@@ /^M/g Пер­вые три ко­манд­ ы да­дут след­ ую­щий ре­зульт­ ат: .KS@@ .IP \"ICON_IMAGE\" 2nn@@ Sets or gets ... image. @@ .KE .KS@@ .IP \"SERVER_SYNC\" 2nn@@ Synchronizes with ... mode. @@ .KE .KS@@ .IP \"TTY_ARGV\" 2nn@@ The ... vector, @@ that ... .@@ .KE .KS@@ .IP \"XV_LABEL\" 2nn@@ Specifies a ... icon's label. @@ .KE Об­ра­ти­те вним­ а­ние на до­полн­ и­тель­ный про­бел по­сле @@. Эти проб­ е­лы поя­ в­ляю­ т­ся от ком­ ан­ды j, по­скольк­ у она пре­об­ра­зу­ет каж­дый пер­ е­вод строк­ и в проб­ ел. Пер­вая ко­ман­да по­меч­ а­ет пер­вон­ а­чальн­ ые пе­рен­ ос­ ы строк симв­ о­лам­ и @@. Кон­ ец блок­ а (по­сле .KE) по­ме­чать не на­до, по­это­му в перв­ ой по­сле­до­ ват­ ель­но­сти стои­ т ко­ман­да -1, пе­рем­ е­щаю­щая курс­ ор от кон­ца бло­ка вверх на одн­ у стро­ку. Четв­ ер­тая ко­манд­ а восс­ тан­ авл­ ив­ а­ет пер­ е­но­сы строк, зам­ е­няя метк­ и (и один проб­ ел) на но­вые строк­ и. Пос­ ле этог­ о файл бу­дет рас­сор­тир­ о­ван по блок­ ам.Комментарии в скриптах ex Воз­можн­ о, вы буд­ ет­ е ис­польз­ ов­ ать этот скрипт нео­ дн­ ок­ рат­но в разн­ ых си­туа­ци­ях. В случ­ ае сложн­ ых скрип­тов, та­ких как в наш­ ем при­ме­ре, раз­ умн­ о до­бавл­ ять комм­ ен­та­рии, что­бы дру­гим поль­зов­ а­те­лям (или да­ же вам) бы­ло легч­ е его ре­кон­стр­ уи­ров­ ать. В скрипт­ ах ex все, что сле­ду­ ет за двой­ной ка­выч­кой, буд­ ет игн­ о­рир­ о­ватьс­ я во вре­мя вы­пол­не­ния, поэ­ том­ у двойн­ ая кав­ ыч­ка от­ме­чае­ т на­ча­ло комм­ ент­ ар­ ия. Комм­ ент­ а­рии мож­но пи­сать в  от­дельн­ ых строк­ ах. Они так­же мог­ ут рас­по­лаг­ ать­ся в конц­ е люб­ ой ком­ анд­ ы, не счи­таю­щей кав­ ыч­ки свое­ й ча­стью. (Нап­ ри­

Редактирование исходного кода программы 143 мер, кав­ ыч­ка име­ет знач­ ен­ ие в ко­ман­дах ото­бра­жен­ ия и обол­ оч­ки. По­ доб­ные строк­ и не мо­гут за­кан­чи­вать­ся комм­ ент­ а­ри­ем.) Кро­ме исп­ оль­зо­ван­ ия комм­ ент­ а­рие­ в мож­но ука­зы­вать пол­ное имя ко­ манд­ ы, что в vi обыч­но не де­ла­ет­ся из-за экон­ о­мии врем­ ен­ и. На­кон­ ец, по­сле до­бав­лен­ ия проб­ е­лов наш ex-скрипт стан­ ет гор­ азд­ о бол­ ее удо­бо­ чи­тае­мым: \" Mark lines between each KS/KE block global /^\.KS/,/^\.KE/-1 s /$/@@/ \" Now join the blocks into one line global /^\.KS/,/^\.KE/ join \" Sort each block--now really one line each %!sort \" Restore the joined lines to original blocks % s /@@ /^M/g Удив­ ит­ ельн­ о, но ко­ман­да substitute в ex не ра­бо­та­ет, хо­тя полн­ ые име­на друг­ их команд ра­бот­ аю­ т.За пределами ex Ес­ли изл­ о­женн­ ый мат­ е­риа­ л проб­ у­дил ваш апп­ ет­ ит к бол­ ее про­дви­ну­ то­му ре­дак­тир­ ов­ а­нию, то не­обх­ од­ им­ о знать, что в  UNIX есть го­раз­до бо­лее мощ­ные ред­ ак­тор­ ы по срав­нен­ ию с ex, так­ ие как по­то­ков­ ый ре­ дакт­ ор sed и язык обр­ аб­ отк­ и данн­ ых awk. Такж­ е сущ­ ес­ т­ву­ет чрезв­ ыч­ ай­ но поп­ у­лярн­ ый язык про­грам­мир­ о­ван­ ия Perl. Есл­ и хо­ти­те узн­ ать боль­ ше об этих про­грамм­ ах, об­рат­ ит­ есь к  книг­ ам O’Reilly: sed & awk, Effective awk Programming, Learning Perl1 и Programming Perl2.Редактирование исходного кода программы Все рас­смот­ренн­ ые выш­ е функц­ ии не от­лич­ а­ли обыч­ный текст от про­ граммн­ ог­ о код­ а. Од­нак­ о сущ­ ес­ т­ву­ет ряд доп­ олн­ ит­ ельн­ ых функ­ций, ко­ тор­ ые бу­дут ин­тер­ ес­ны именн­ о про­грамм­ и­стам. Так­ о­вым­ и яв­ляю­ тс­ я кон­троль отс­ туп­ ов, по­иск на­чал­ а и конц­ а проц­ ед­ ур­ ы и ис­поль­зо­ва­ние ctags. Даль­нейш­ ее из­ло­же­ние осн­ о­ван­ о на до­ку­мент­ ац­ ии, пред­ ост­ авл­ ен­ной Mortice Kern Systems для их прек­ рас­ной реа­лиз­ а­ции vi для сис­тем DOS и  Windows, дос­тупн­ ой в  вид­ е час­ти MKS Toolkit или отд­ ельн­ ой про­ грам­мы MKS Vi. Вос­про­из­во­дитс­ я с раз­реш­ ен­ ия Mortice Kern Systems.1 Рэнд­ ал Шварц, Том Фе­никс и Брай­ан Д. Фой «Изуч­ а­ем Perl», 5-е издание. – Пер. с англ. – Симв­ ол-Плюс, 2009.2 Лар­ри Уолл, Том Кри­сти­анс­ ен, Джон Орвант «Программирование на Perl», 3-е издание. – Пер. с англ. – Симв­ ол-Плюс, 2002.

144 Глава 7. Продвинутое редактированиеКонтроль за отступами Прог­ раммн­ ый код нес­ коль­ко от­лич­ ае­ т­ся от обыч­но­го тек­ста. Один из асп­ ек­тов ка­са­етс­ я ис­польз­ ов­ а­ния отс­ туп­ ов в код­ е, где они по­каз­ ы­ва­ют ло­ги­че­скую струк­тур­ у про­грамм­ ы, то есть спо­соб объе­ ди­нен­ ия строк в блок­ и. vi да­ет воз­мож­ность авт­ о­ма­ти­че­ски конт­ рол­ и­ров­ ать отс­ ту­пы. Чтоб­ ы исп­ оль­зо­вать это, вве­дит­ е ком­ ан­ду: :set autoindent Те­перь при ус­та­новк­ е отс­ туп­ а в стро­ке про­бе­ла­ми или та­бу­ляц­ и­ей та­ кие же отс­ ту­пы уст­ а­но­вятс­ я во всех пос­ лед­ ующ­ их строк­ ах. По­сле на­ жат­ ия на ENTER в конц­ е перв­ ой стро­ки с отс­ ту­пом кур­сор пе­ре­мес­тит­ ся на нов­ ую стро­ку и ав­том­ ат­ ич­ е­ски от­сту­пит на то же рас­стоян­ ие, что и в пред­ ыд­ у­щей. Есл­ и вы прог­ рамм­ ист, то смо­же­те сэкон­ о­мить мног­ о вре­ме­ни на ус­та­ нов­ке от­ступ­ ов, осо­бен­но ес­ли у вас есть не­сколь­ко уров­ней от­сту­пов. При ввод­ е текс­ та с включ­ енн­ ой опц­ и­ей autoindent на­жат­ ие CTRL-T в на­ ча­ле строк­ и пе­рев­ е­дет кур­сор на след­ ующ­ ий уро­вень отс­ туп­ а, а CTRL-D верн­ ет его обр­ атн­ о. Отм­ е­тим, что CTRL-T и CTRL-D долж­ны ввод­ ить­ся в реж­ им­ е встав­ки, в от­ли­чие от мно­гих друг­ их ком­ анд, ко­то­рые на­би­раю­ т­ся в ко­манд­ном реж­ им­ е. Есть два друг­ их ва­риа­ нт­ а при­мен­ ен­ ия ком­ анд­ ы CTRL-D1: ^ ^D Ес­ли ввес­ ти ^ ^D (^ CTRL-D), то vi пер­ ем­ ес­тит кур­сор на­зад на нач­ а­ло стро­ки, но тольк­ о для те­кущ­ ей строк­ и. След­ ующ­ ая стро­ка начн­ ет­ся на те­кущ­ ем уст­ а­нов­лен­ном авт­ о­мат­ и­че­ски уровн­ е отс­ ту­па. Это мо­ жет быть пол­ ез­но при вво­де ком­ анд преп­ роц­ есс­ ор­ а C в про­грамм­ ах на C/C++. 0 ^D При на­жа­тии 0 ^D vi пер­ ем­ ес­тит курс­ ор обр­ ат­но на на­ча­ло строк­ и. Вдо­бав­ ок к это­му те­кущ­ ий уров­ ень отс­ туп­ а ста­нет ну­лев­ ым, и сле­ дующ­ ая строк­ а бу­дет уже без отс­ туп­ а2. По­про­буй­те опц­ ию autoindent при ввод­ е про­граммн­ ог­ о код­ а. Она уп­ро­ стит раб­ от­ у по упор­ яд­ о­чив­ ан­ ию отс­ туп­ ов. А в нек­ о­то­рых слу­ча­ях пом­ о­ жет из­беж­ ать ошибо­ к, на­прим­ ер в про­грамм­ е на C, где тре­буе­ т­ся од­на за­кры­вающ­ ая фиг­ урн­ ая скоб­ка (}) для кажд­ ог­ о возв­ рат­ а на пре­ды­ду­ щий уров­ ень отс­ туп­ а. При ус­тан­ овк­ е от­сту­пов в про­грам­ме такж­ е мог­ ут быть по­лез­ны­ми ко­ манд­ ы >> и  <<. По умол­чан­ ию >> сме­щае­ т стро­ку на во­семь проб­ ел­ ов 1 В elvis это раб­ о­тать не бу­дет. 2 В до­кум­ ент­ а­ция nvi 1.79 эти две ко­ман­ды пе­реп­ ут­ а­ны, но про­грам­ма вед­ ет себ­ я именн­ о так, как мы опис­ ал­ и.

Редактирование исходного кода программы 145впра­во (то есть до­бав­ля­ет к от­ступ­ у эти во­семь проб­ ел­ ов), а << – на во­семь проб­ ел­ ов влев­ о. На­прим­ ер, пер­ ем­ ест­ ив кур­сор на нач­ ал­ о стро­кии на­брав >>, вы уви­ди­те, как стро­ка сме­ститс­ я впра­во. Есл­ и вве­сти <<, тостро­ка вер­нетс­ я на прежнее ме­сто.Мож­но смес­ тить нес­ кольк­ о строк, указ­ ав их ко­лич­ е­ств­ о пе­ред >> или <<.Нап­ ри­мер, по­мес­ти­те кур­сор на пер­вую стро­ку больш­ ог­ о абзаца и вве­дит­ е 5>>. Пос­ ле этог­ о перв­ ые пять строк в этом абзаце сдви­нутс­ я вправ­ о.По умол­ча­нию ве­лич­ и­на сдвиг­ а равн­ а восьм­ и проб­ е­лам (влев­ о иливправ­ о). Это знач­ е­ние можн­ о из­мен­ ить след­ ующ­ ей ко­манд­ ой: :set shiftwidth=4Вы увид­ и­те, что цел­ е­со­обр­ аз­но уст­ ан­ ов­ ить shiftwidth рав­ным ши­ри­нета­бу­ля­ции.При уст­ а­новк­ е отс­ туп­ ов vi пы­тае­ т­ся умн­ ич­ ать. Как прав­ и­ло, при на­ли­чии тек­ста с отс­ туп­ ом из восьм­ и про­бе­лов он встав­ ит в файл симв­ о­лыта­бул­ яц­ ии, по­то­му что обыч­но таб­ у­ля­ция за­ме­няе­ т­ся вос­ ем­ ью про­бе­ла­ми. Это при­нят­ о в UNIX, од­нак­ о лег­ко зам­ е­тить, что при ввод­ е та­бу­ля­ции и печ­ а­ти фай­ла на принт­ ер­ е UNIX за­ме­нит ее на во­семь про­бе­лов.При жел­ а­нии можн­ о из­ме­нить спос­ об предс­ тавл­ ен­ ия таб­ у­ляц­ ии на эк­ра­не, по­мен­ яв опц­ ию tabstop. На­прим­ ер, ес­ли у  вас больш­ ой уро­веньвло­женн­ ос­ ти бло­ков, мож­но взять че­тыр­ е симв­ о­ла для таб­ ул­ я­ции, что­бы строк­ и по­мещ­ а­лись на строк­ е. Так­ ую за­мен­ у прои­ з­вед­ ет след­ ую­щаяко­манд­ а: :set tabstop=4 Мен­ ять ши­ри­ну таб­ ул­ яц­ ии не ре­ком­ ен­дуе­ т­ся. Хо­тя vi и буд­ ет ото­ браж­ ать файл при люб­ ом зна­че­нии tabstop, в ост­ альн­ ых про­грам­ мах UNIX знак­ и таб­ ул­ яц­ ии бу­дут1 зам­ ен­ ятьс­ я на во­семь про­бе­лов. Хуж­ е то­го: смесь проб­ ел­ ов, таб­ у­ля­ций и нео­ бычн­ ых поз­ иц­ ий та­бу­ ляц­ ии сде­лае­ т ваш файл сов­ ер­шенн­ о не­чи­таем­ ым в друг­ их прог­ рам­ мах, та­ких как про­грамм­ а по­стра­ничн­ о­го вы­во­да more, или при рас­ печ­ атк­ е. Вось­ми­симв­ ольн­ ая табуляция – это одн­ а из данн­ ос­ тей UNIX, и вам при­дет­ся с этим сми­рить­ся.Иног­ да от­сту­пы не раб­ о­таю­ т как над­ о, по­том­ у что симв­ ол таб­ у­ляц­ ии напро­верк­ у ока­зы­ва­етс­ я не­сколь­ким­ и проб­ ел­ ам­ и. Как пра­ви­ло, на экр­ а­не таб­ у­ля­ция и  проб­ ел ото­браж­ аю­ тс­ я один­ а­ков­ о, и  их не раз­ли­чить.Од­на­ко можн­ о вы­пол­нить сле­дую­щую ко­ман­ду: :set list1 По крайн­ ей мер­ е, мо­гут: в не­кот­ ор­ ых при­лож­ е­ни­ях UNIX, особ­ енн­ о со­вре­ менн­ ых, шир­ и­ну таб­ ул­ я­ции такж­ е мож­но ре­гу­ли­ров­ ать. Но в люб­ ом случ­ ае изм­ ен­ ен­ ие зна­чен­ ия tabstop в vi вылье­ т­ся в ­лишн­ юю ра­бо­ту. – Прим. нау­ ч. ред.

146 Глава 7. Продвинутое редактирование При этом ото­браж­ е­ние смен­ итс­ я так­ им об­ра­зом, что та­бу­ляц­ ия бу­дет по­ка­за­на в  ви­де управл­ яющ­ е­го симв­ о­ла ^I, а  ко­нец строки – как $. В этом слу­чае можн­ о расп­ о­знать реа­ льн­ ые про­бел­ ы и уви­деть лишн­ ие в  конц­ е стро­ки. Врем­ енн­ ым эк­вив­ а­лент­ ом это­го яв­ля­ет­ся ко­манд­ а :l. На­при­мер, пос­ лед­ о­ва­тельн­ ость: :5,20 l отоб­ ра­зит сим­во­лы таб­ ул­ яц­ ии и конц­ а строк­ и в стро­ках с 5-й по 20-ю.Специальная команда поиска Симв­ о­лы (, [, { и < мо­гут быть от­крыв­ аю­щи­ми скоб­ка­ми. Ког­ да курс­ ор на­хо­дит­ся на од­ном из этих симв­ ол­ ов, на­жа­тие кла­ви­ши % пер­ ем­ ест­ ит его с отк­ ры­той скобк­ и впе­ред на со­от­ветс­ тв­ ующ­ ую зак­ ры­ваю­щую: ), ], } или > с учет­ ом обыч­ног­ о пра­вил­ а для влож­ енн­ ых ско­бок1. Нап­ ри­мер, ес­ли пос­ та­вить курс­ ор на перв­ ую ( в выр­ аж­ ен­ ии: if ( cos(a[i]) == sin(b[i]+c[i]) ) { printf(\"cos and sin equal!\n\"); } и на­жать %, то курс­ ор пе­ре­прыгн­ ет на скоб­ку в конц­ е этой стро­ки. Это за­крыв­ ающ­ ая скоб­ка, соо­ тв­ етс­ т­вую­щая отк­ ры­вающ­ ей, на ко­то­рой сто­ ял курс­ ор. Ана­ло­гич­но, есл­ и курс­ ор сто­ит на од­ном из симв­ о­лов зак­ ры­вающ­ их скоб­ ок, то наж­ ат­ ие % пе­рем­ ес­тит его наз­ ад на со­отв­ етс­ тв­ ую­щую от­кры­ ваю­щую скоб­ку. На­прим­ ер, по­ставьт­ е кур­сор на зак­ ры­ваю­щую скобк­ у по­сле строк­ и с printf и на­жмит­ е %. vi дос­та­точн­ о умен и мо­жет сам найт­ и симв­ ол скобк­ и. Есл­ и кур­сор сто­ ит не на симв­ о­ле скобк­ и, то при вво­де % ред­ акт­ ор буд­ ет ис­кать впер­ ед по тек­ у­щей строк­ е до перв­ о­го по­пав­ше­го­ся сим­во­ла отк­ рыв­ аю­щей или за­ кры­вающ­ ей скоб­ки и пер­ ем­ ес­тит курс­ ор на соо­ т­вет­ст­вую­щую ей скоб­ ку! На­прим­ ер, есл­ и в пред­ ыд­ у­щем при­ме­ре кур­сор в пер­вой стро­ке сто­ ит на сим­во­ле >, то % оты­щет от­крыв­ аю­щую круг­лую скобк­ у и пер­ е­мес­ тит курс­ ор на за­кры­ваю­щую. Симв­ ол по­ис­ка % по­зво­ляе­ т не толь­ко быс­ тр­ о пер­ ем­ е­щать­ся впе­ред и на­ зад по про­грамм­ е, но и пров­ е­рять вло­женн­ ость ско­бок в прог­ раммн­ ом код­ е. Нап­ рим­ ер, есл­ и по­став­ ить кур­сор на перв­ ую { в на­чал­ е функ­ции C, то ввод % пер­ е­мест­ ит кур­сор на ту }, ко­тор­ ая, по идее, зав­ ер­шае­ т функц­ ию. Есл­ и это не так, зна­чит, где-то со­держ­ ит­ся ошибк­ а. Ког­ да со­ отв­ ет­ств­ ующ­ ая } не най­ден­ а, vi вы­даст зву­ко­вой сиг­нал. 1 Из всех про­тес­тир­ о­ван­ных вер­сий со­отв­ етс­ тв­ ие < и > при исп­ ольз­ ов­ а­нии % наб­ люд­ ал­ ось тольк­ о в nvi. В vile (и Vim. – Прим. на­уч. ред.) можн­ о зад­ ать опц­ ию, где оп­ред­ е­ляе­ т­ся, как­ ие пар­ ы сим­во­лов бу­дут соо­ тв­ ет­ст­вов­ ать друг друг­ у при на­жат­ ии %.

Редактирование исходного кода программы 147 Друг­ ой спо­соб иск­ ать скобк­ и, соо­ т­вет­ств­ ующ­ ие друг друж­ке, сос­ тои­ т во вклю­чен­ ии след­ ую­щей опц­ ии: :set showmatch Включ­ ен­ ие showmatch (или ее аб­брев­ иа­ту­ры sm) отл­ и­чае­ тс­ я от % тем, что раб­ о­тае­ т в реж­ и­ме встав­ки. При вво­де ) или }1 кур­сор на ко­ротк­ ое вре­ мя пер­ е­мест­ ит­ся на со­отв­ етс­ т­вую­щую ( или {, а за­тем вер­нетс­ я на ис­ ходн­ ую по­зиц­ ию. Ес­ли со­от­вет­ств­ ие не бу­дет найд­ е­но, вы усл­ ыш­ ит­ е звук­ ов­ ой сиг­нал. Ес­ли со­отв­ ет­ст­вую­щая скобк­ а не поп­ а­да­ет на те­ку­ щий экр­ ан, vi прод­ ол­жит раб­ о­ту без зву­ков­ ых опо­вещ­ е­ний. Vim 7.0 и его бол­ ее поздн­ ие вер­сии мо­гут подс­ веч­ ив­ ать соо­ тв­ етс­ т­вую­щие друг дру­гу скоб­ки, ис­поль­зуя за­груж­ ае­мый по умолч­ а­нию пла­гин matchparen.Использование тегов Обыч­но ис­ход­ный код больш­ их про­грамм на C или C++ раз­бит на не­ скольк­ о файл­ ов. Ино­гда очень слож­но отс­ лед­ ить, ка­кой из них сод­ ер­ жит опис­ ан­ ие нужн­ ой функц­ ии. Чтоб­ ы упр­ ос­ тить дел­ о, ком­ анд­ а UNIX ctags мо­жет исп­ оль­зов­ ать­ся со­вме­ст­но с ко­ман­дой :tag из vi. UNIX-верс­ ии ctags подд­ ер­жив­ а­ют язык­ и C и, чащ­ е все­го, Pascal и Fortran 77. Иног­ да они даж­ е подд­ ерж­ и­ваю­ т язык ас­семб­лер­ а. C++, как прав­ и­ло, не под­дер­жи­ва­етс­ я. Дос­тупн­ ы дру­гие вер­сии, ко­то­рые мог­ ут выр­ а­бат­ ыв­ ать файл­ ы tags для C++ и друг­ их язык­ ов и тип­ ов фай­лов. За бо­лее подр­ об­ной ин­форм­ а­цие­ й обр­ ат­ ит­ есь к  разд­ е­лу «Улучш­ ен­ные те­ги» на стр. 154. Сна­чал­ а нужн­ о выз­ вать ком­ анд­ у ctags в  ко­мандн­ ой стро­ке UNIX. Ее цель – созд­ ать инф­ ор­ма­цио­ нн­ ый файл, ко­то­рый в  даль­ней­шем бу­дет ис­польз­ ов­ атьс­ я в vi для оп­ре­де­ле­ния, в ка­ком файл­ е как­ ие функ­ции со­ дер­жатс­ я. По умол­чан­ ию этот файл на­зы­вае­ тс­ я tags. В vi ко­манд­ а сле­ дую­щег­ о ви­да: :!ctags file.c соз­даст в тек­ у­щем кат­ а­ло­ге файл с имен­ ем tags, со­дер­жащ­ ий ин­форм­ а­ цию о функц­ и­ях, оп­ред­ е­лен­ных в file.c. Сле­дующ­ ая ко­манд­ а :!ctags *.c созд­ аст файл tags, опи­сыв­ аю­щий все фай­лы ис­ход­но­го код­ а C в  тек­ у­ щем кат­ а­лог­ е. Те­перь предп­ о­ло­жим, что файл tags со­держ­ ит инф­ ор­мац­ ию обо всех файл­ ах ис­ход­но­го код­ а, из ко­тор­ ых соб­ р­ а­на про­грамм­ а на C. Так­же до­ пуст­ им, что нужн­ о най­ти и отр­ е­дак­ти­ров­ ать функ­цию из этой про­грам­ мы, но вы не знае­те, где расп­ ол­ а­гае­ тс­ я эта функ­ция. Ком­ анд­ а в vi: :tag name 1 В  elvis, Vim и  vile showmatch так­же пок­ аз­ ы­вае­ т соо­ тв­ етс­ т­вие для квадр­ ат­ ных скоб­ ок [ и ].

148 Глава 7. Продвинутое редактирование ищет в фай­ле tags файл, сод­ ер­жа­щий опр­ е­дел­ е­ние функц­ ии name. За­ тем эта ком­ ан­да счи­ты­вае­ т этот файл и по­ме­щае­ т курс­ ор на строк­ у с оп­ ре­дел­ ен­ и­ем name. При этом необя­зат­ ельн­ о знать, как­ ой файл вы ред­ ак­ тир­ уе­те. Нуж­но лишь реш­ ить, ка­кую функ­цию сле­дуе­ т изм­ ен­ ить. Воз­мож­нос­ тя­ми тег­ ов можн­ о поль­зов­ атьс­ я и  в  ко­мандн­ ом ре­жим­ е vi. Пом­ ест­ и­те кур­сор на иден­ти­фик­ а­тор, кот­ ор­ ый вы хот­ и­те оты­скать, и введ­ ит­ е ^]. vi про­изв­ е­дет по­иск по тег­ ам и пер­ ем­ ест­ ит вас в файл, где этот иден­тиф­ ик­ ат­ ор опр­ ед­ ел­ ен. Будь­те ос­тор­ ож­ны с по­ло­жен­ и­ем курсо- ра – vi счи­та­ет «слов­ ом» то, что на­чин­ а­ет­ся с те­кущ­ ей поз­ иц­ ии курс­ о­ ра, а не все слов­ о, где сто­ит курс­ ор. Ес­ли вы пыт­ ает­ есь исп­ оль­зов­ ать ком­ анд­ у :tag для счи­тыв­ а­ния фай­ ла, но не со­хран­ ил­ и те­кущ­ ий файл со врем­ е­ни его пос­ ледн­ ег­ о изм­ е­ нен­ ия, vi не по­звол­ ит пе­рейт­ и на нов­ ый файл. Нуж­но ли­бо сох­ ра­ нить тек­ ущ­ ий файл ком­ анд­ ой :w и тольк­ о по­сле этог­ о вы­звать :tag, либ­ о вып­ ол­нить сле­дую­щую ко­ман­ду: :tag! name кот­ ор­ ая пе­ре­сил­ ит неж­ е­ла­ние vi от­бра­сы­вать из­мен­ ен­ ия. Верс­ ия vi для Solaris тож­ е под­держ­ и­ва­ет сте­ки тег­ ов, одн­ а­ко эта воз­ можн­ ость не от­ра­же­на в док­ у­мен­та­ции к Solaris. По­скольк­ у мног­ ие, ес­ ли не больш­ инс­ т­во, вер­сии vi не подд­ ер­жив­ аю­ т стек­ и те­гов, мы пер­ е­ мест­ и­ли обс­ уж­ ­ден­ ие этой функц­ ии в раз­дел «Стек­ и тег­ ов» на стр. 157, где подр­ обн­ ее по­зна­ко­мим вас с ним­ и.

8 Представляем клоны vi Глава 8.Знакомьтесь: Даррелл, Даррелл и ДарреллСущ­ ес­ т­ву­ет нес­ кольк­ о сво­бодн­ о рас­про­стран­ яем­ ых мо­ди­фик­ ац­ ий ре­дак­тор­ а vi. При­лож­ е­ние D дае­ т ссыл­ку на веб-сайт, где пер­ е­числ­ е­ны всеего из­вестн­ ые раз­нов­ идн­ о­сти, а  в  част­ и II под­роб­но расс­ ка­зы­ва­етс­ яо Vim. Часть III ка­сае­ т­ся трех дру­гих поп­ ул­ ярн­ ых мод­ и­фик­ ац­ ий vi:• nvi вер­сия 1.79 Кей­та Бост­ и­ча (Keith Bostic) (глава 16)• elvis верс­ ия 2.2.0 Стив­ а Кирк­ ен­далл­ а (Steve Kirkendall) (глава 17)• vile верс­ ия 9.6.4 Ке­вин­ а Буттн­ ер­ а (Kevin Buettner), То­ма Дик­ и (Tom Dic­ ­key), Пол­ а Фок­са (Paul Fox) и  Кларк­ а Мор­ган­ а (Clark Morgan) (глав­ а 18)Все они бы­ли на­пи­сан­ ы либ­ о из-за огр­ а­нич­ е­ний на своб­ одн­ ое расп­ рос­ тра­не­ние ис­ходн­ ог­ о ко­да vi, что дел­ а­ло нев­ оз­мож­ным пе­рен­ ос ред­ ак­то­рав не-UNIX ок­руж­ е­ние и изу­че­ние его код­ а, либо из-за тог­ о, что vi (илидру­гой клон!) для UNIX не имел треб­ уе­мой функ­цио­нальн­ ос­ ти. Нап­ ри­мер, vi для UNIX част­ о име­ет пред­ ел макс­ им­ аль­ной дли­ны строк­ ии в нем нель­зя ре­дакт­ и­ров­ ать бин­ арн­ ые файл­ ы. (Глав­ ы, по­свя­щен­ныесоо­ т­ветс­ т­вующ­ им про­грамм­ ам, расс­ каж­ ут боль­ше об их ист­ о­рии.)В кажд­ ой про­грам­ме есть множ­ ес­ т­во рас­ши­ре­ний по срав­не­нию с vi дляUNIX. Зач­ ас­тую одн­ и и  те же доп­ олн­ ен­ ия, возм­ ожн­ о, реал­ из­ ов­ ан­ныепо-раз­но­му, есть у нес­ коль­ких мод­ иф­ ик­ а­ций. Чтоб­ ы не по­вто­рять в каж­дой гла­ве опи­са­ние одн­ ой и той же об­щей для всех прог­ рамм функ­ции,мы вы­вел­ и их обс­ у­жд­ ен­ ие сюд­ а. Мо­жет­ е рас­смат­рив­ ать эту гла­ву какрас­сказ о функ­цион­ альн­ о­сти мод­ и­фи­кац­ ий ре­дакт­ о­ра. При этом гла­ва,пос­ вя­щенн­ ая кажд­ ом­ у клон­ у, рас­ска­зыв­ ае­ т, как они ра­бо­таю­ т.Те­мы этой глав­ ы пред­ставл­ ен­ ы дал­ ее в  том же пор­ яд­ке, но бол­ ее по­дробн­ о в части II, по­свящ­ енн­ ой Vim, и го­разд­ о бол­ ее компактно – в гла­вах част­ и III. В данн­ ой гла­ве мы расс­ мот­рим сле­дую­щие тем­ ы:

150 Глава 8. Представляем клоны vi Мног­ оо­ конн­ ое ред­ ак­ти­ров­ ан­ ие Это воз­можн­ ость разд­ е­лить экр­ ан (тер­мин­ ал­ а) на не­сколь­ко «окон» и/или ис­польз­ ов­ ать их в граф­ и­че­ском ок­ру­же­нии. При этом в ок­нах мож­но ред­ акт­ ир­ о­вать раз­ные файл­ ы или дер­жать разн­ ые ви­ды одн­ о­ го файл­ а. Возм­ ожн­ о, это сам­ ое главн­ ое улуч­шен­ ие ориг­ и­нальн­ о­го vi. Граф­ и­чес­ кие инт­ ер­фейс­ ы Все клон­ ы, за иск­ лю­чен­ ие­ м nvi, мо­гут быть скомп­ ил­ и­ров­ ан­ ы с под­ держ­кой ин­тер­фей­са X Window. Ес­ли в ва­шей сист­ е­ме ра­бо­тае­ т X, то ис­поль­зо­ван­ ие GUI-вер­сии мож­ ет быть предп­ оч­ти­тель­нее разд­ ел­ е­ ния экр­ ан­ а xterm (или друг­ о­го эмул­ я­тор­ а терм­ ин­ ал­ а). Как пра­вил­ о, GUI-вер­сии обесп­ еч­ ен­ ы и дру­гим­ и пол­ езн­ ым­ и функц­ иям­ и, так­ им­ и как пол­ ос­ ы про­крутк­ и и  разн­ ые шриф­ты. Такж­ е мог­ ут под­держ­ и­ вать­ся GUI из дру­гих опер­ ац­ и­онн­ ых сис­тем. Расш­ и­ренн­ ые ре­гул­ яр­ные вы­раж­ ен­ ия Все мод­ иф­ и­кац­ ии vi по­звол­ яю­ т иск­ ать текст при пом­ ощ­ и рег­ ул­ яр­ ных выр­ аж­ е­ний, кот­ о­рые пох­ о­жи или совп­ а­даю­ т с ис­поль­зуе­мым­ и в ко­ман­де egrep UNIX. Улуч­шенн­ ые тег­ и Как уже опи­сыв­ а­лось в разд­ ел­ е «Исп­ ольз­ ов­ ан­ ие тег­ ов» на стр. 147, при по­строе­нии ба­зы данн­ ых для пои­ ск­ а в файл­ ах можн­ о ис­поль­зо­ вать про­грам­му ctags. Мо­диф­ и­ка­ции vi так­же поз­ вол­ я­ют созд­ ав­ ать «стек­ и тег­ ов» (tag stack), пос­ лед­ о­ват­ ельн­ о сох­ ран­ яя ва­ше те­ку­щее мес­ то­по­лож­ е­ние во вре­мя пои­ с­ка по те­гам. Впо­следс­ т­вии можн­ о вер­ нуть­ся к сох­ ран­ енн­ ом­ у мес­ту. Пос­ ле­дов­ ат­ ельн­ ость ме­сто­пол­ о­же­ний со­хран­ яе­ тс­ я в  по­ряд­ке «перв­ ым при­шел, пос­ лед­ним ушел» (LIFO), форм­ ир­ уя стек пол­ ож­ ен­ ий. Не­ко­тор­ ые ав­тор­ ы мод­ и­фи­ка­ций vi и авт­ ор по край­ней мер­ е одн­ ой разн­ о­видн­ ос­ ти ctags приш­ ли к  сог­ ла­ше­нию, оп­ре­де­ляющ­ е­му стан­ дартн­ ую фор­му улучш­ енн­ ой вер­сии фор­мат­ а ctags. В час­ тн­ ос­ ти, сей­ час про­ще ис­польз­ о­вать функц­ ио­нальн­ ость те­гов в про­грамм­ ах, на­ пис­ анн­ ых на C++, где разр­ е­ше­на пе­рег­ руз­ка имен функ­ций. Улуч­шенн­ ые воз­мож­но­сти ред­ ак­ти­ро­ва­ния Во всех мод­ иф­ ик­ а­ци­ях vi есть возм­ ож­ность ре­дак­тир­ о­ван­ ия ко­манд­ ной стро­ки ex, функ­ция «беск­ он­ ечн­ ой отм­ е­ны», строк­ и прои­ зв­ оль­ ной длин­ ы и  сод­ ер­жи­мо­го (подд­ ерж­ка люб­ ых 8-раз­ряд­ных симв­ о­ лов), инк­ рем­ ент­ный пои­ ск, опц­ ия прок­ рутк­ и эк­ра­на сле­ва нап­ ра­во вмес­ то пер­ е­нос­ а при чте­нии длинн­ ых строк, ин­дик­ ат­ о­ры реж­ и­ма и друг­ ие функ­ции. Пом­ ощь про­грам­ми­сту Не­ко­то­рые ре­дак­то­ры пре­дост­ ав­ля­ют возм­ ожн­ ость не вы­хо­дить из прог­ рамм­ ы при вып­ ол­нен­ ии тип­ ичн­ о­го цик­ла разр­ а­ботк­ и ПО «ре­ дакт­ и­ро­ва­ние-ком­пил­ яц­ ия-отл­ адк­ а».


Like this book? You can publish your book online for free in a few minutes!
Create your own flipbook