viper-cmd.el 174 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099
  1. ;;; viper-cmd.el --- Vi command support for Viper
  2. ;; Copyright (C) 1997-2012 Free Software Foundation, Inc.
  3. ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
  4. ;; Package: viper
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. (provide 'viper-cmd)
  19. ;; Compiler pacifier
  20. (defvar viper-minibuffer-current-face)
  21. (defvar viper-minibuffer-insert-face)
  22. (defvar viper-minibuffer-vi-face)
  23. (defvar viper-minibuffer-emacs-face)
  24. (defvar viper-always)
  25. (defvar viper-mode-string)
  26. (defvar viper-custom-file-name)
  27. (defvar viper--key-maps)
  28. (defvar viper--intercept-key-maps)
  29. (defvar iso-accents-mode)
  30. (defvar quail-mode)
  31. (defvar quail-current-str)
  32. (defvar mark-even-if-inactive)
  33. (defvar init-message)
  34. (defvar viper-initial)
  35. (defvar undo-beg-posn)
  36. (defvar undo-end-posn)
  37. (eval-and-compile
  38. (unless (fboundp 'declare-function) (defmacro declare-function (&rest r))))
  39. ;; end pacifier
  40. (require 'viper-util)
  41. (require 'viper-keym)
  42. (require 'viper-mous)
  43. (require 'viper-macs)
  44. (require 'viper-ex)
  45. ;; Generic predicates
  46. ;; These test functions are shamelessly lifted from vip 4.4.2 by Aamod Sane
  47. ;; generate test functions
  48. ;; given symbol foo, foo-p is the test function, foos is the set of
  49. ;; Viper command keys
  50. ;; (macroexpand '(viper-test-com-defun foo))
  51. ;; (defun foo-p (com) (consp (memq com foos)))
  52. (defmacro viper-test-com-defun (name)
  53. (let* ((snm (symbol-name name))
  54. (nm-p (intern (concat snm "-p")))
  55. (nms (intern (concat snm "s"))))
  56. `(defun ,nm-p (com)
  57. (consp (viper-memq-char com ,nms)
  58. ))))
  59. ;; Variables for defining VI commands
  60. ;; Modifying commands that can be prefixes to movement commands
  61. (defvar viper-prefix-commands '(?c ?d ?y ?! ?= ?# ?< ?> ?\"))
  62. ;; define viper-prefix-command-p
  63. (viper-test-com-defun viper-prefix-command)
  64. ;; Commands that are pairs eg. dd. r and R here are a hack
  65. (defconst viper-charpair-commands '(?c ?d ?y ?! ?= ?< ?> ?r ?R))
  66. ;; define viper-charpair-command-p
  67. (viper-test-com-defun viper-charpair-command)
  68. (defconst viper-movement-commands '(?b ?B ?e ?E ?f ?F ?G ?h ?j ?k ?l
  69. ?H ?M ?L ?n ?t ?T ?w ?W ?$ ?%
  70. ?^ ?( ?) ?- ?+ ?| ?{ ?} ?[ ?] ?' ?`
  71. ?\; ?, ?0 ?? ?/ ?\ ?\C-m
  72. space return
  73. delete backspace
  74. )
  75. "Movement commands")
  76. ;; define viper-movement-command-p
  77. (viper-test-com-defun viper-movement-command)
  78. ;; Vi digit commands
  79. (defconst viper-digit-commands '(?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
  80. ;; define viper-digit-command-p
  81. (viper-test-com-defun viper-digit-command)
  82. ;; Commands that can be repeated by . (dotted)
  83. (defconst viper-dotable-commands '(?c ?d ?C ?s ?S ?D ?> ?<))
  84. ;; define viper-dotable-command-p
  85. (viper-test-com-defun viper-dotable-command)
  86. ;; Commands that can follow a #
  87. (defconst viper-hash-commands '(?c ?C ?g ?q ?s))
  88. ;; define viper-hash-command-p
  89. (viper-test-com-defun viper-hash-command)
  90. ;; Commands that may have registers as prefix
  91. (defconst viper-regsuffix-commands '(?d ?y ?Y ?D ?p ?P ?x ?X))
  92. ;; define viper-regsuffix-command-p
  93. (viper-test-com-defun viper-regsuffix-command)
  94. (defconst viper-vi-commands (append viper-movement-commands
  95. viper-digit-commands
  96. viper-dotable-commands
  97. viper-charpair-commands
  98. viper-hash-commands
  99. viper-prefix-commands
  100. viper-regsuffix-commands)
  101. "The list of all commands in Vi-state.")
  102. ;; define viper-vi-command-p
  103. (viper-test-com-defun viper-vi-command)
  104. ;; Where viper saves mark. This mark is resurrected by m^
  105. (defvar viper-saved-mark nil)
  106. ;; Contains user settings for vars affected by viper-set-expert-level function.
  107. ;; Not a user option.
  108. (defvar viper-saved-user-settings nil)
  109. ;;; CODE
  110. ;; sentinels
  111. ;; Runs viper-after-change-functions inside after-change-functions
  112. (defun viper-after-change-sentinel (beg end len)
  113. (run-hook-with-args 'viper-after-change-functions beg end len))
  114. ;; Runs viper-before-change-functions inside before-change-functions
  115. (defun viper-before-change-sentinel (beg end)
  116. (run-hook-with-args 'viper-before-change-functions beg end))
  117. (defsubst viper-post-command-sentinel ()
  118. (condition-case conds
  119. (run-hooks 'viper-post-command-hooks)
  120. (error (viper-message-conditions conds)))
  121. (if (eq viper-current-state 'vi-state)
  122. (viper-restore-cursor-color 'after-insert-mode)))
  123. (defsubst viper-pre-command-sentinel ()
  124. (run-hooks 'viper-pre-command-hooks))
  125. ;; Needed so that Viper will be able to figure the last inserted
  126. ;; chunk of text with reasonable accuracy.
  127. (defsubst viper-insert-state-post-command-sentinel ()
  128. (if (and (memq viper-current-state '(insert-state replace-state))
  129. viper-insert-point
  130. (>= (point) viper-insert-point))
  131. (setq viper-last-posn-while-in-insert-state (point-marker)))
  132. (or (viper-overlay-p viper-replace-overlay)
  133. (progn
  134. (viper-set-replace-overlay (point-min) (point-min))
  135. (viper-hide-replace-overlay)))
  136. (if (eq viper-current-state 'insert-state)
  137. (let ((icolor (viper-frame-value viper-insert-state-cursor-color)))
  138. (or (stringp (viper-get-saved-cursor-color-in-insert-mode))
  139. (string= (viper-get-cursor-color) icolor)
  140. ;; save current color, if not already saved
  141. (viper-save-cursor-color 'before-insert-mode))
  142. ;; set insert mode cursor color
  143. (viper-change-cursor-color icolor)))
  144. (let ((ecolor (viper-frame-value viper-emacs-state-cursor-color)))
  145. (when (and ecolor (eq viper-current-state 'emacs-state))
  146. (or (stringp (viper-get-saved-cursor-color-in-emacs-mode))
  147. (string= (viper-get-cursor-color) ecolor)
  148. ;; save current color, if not already saved
  149. (viper-save-cursor-color 'before-emacs-mode))
  150. ;; set emacs mode cursor color
  151. (viper-change-cursor-color ecolor)))
  152. (if (and (memq this-command '(dabbrev-expand hippie-expand))
  153. (integerp viper-pre-command-point)
  154. (markerp viper-insert-point)
  155. (marker-position viper-insert-point)
  156. (> viper-insert-point viper-pre-command-point))
  157. (viper-move-marker-locally viper-insert-point viper-pre-command-point)))
  158. (defsubst viper-preserve-cursor-color ()
  159. (or (memq this-command '(self-insert-command
  160. viper-del-backward-char-in-insert
  161. viper-del-backward-char-in-replace
  162. viper-delete-backward-char
  163. viper-join-lines
  164. viper-delete-char))
  165. (memq (viper-event-key last-command-event)
  166. '(up down left right (meta f) (meta b)
  167. (control n) (control p) (control f) (control b)))))
  168. (defsubst viper-insert-state-pre-command-sentinel ()
  169. (or (viper-preserve-cursor-color)
  170. (viper-restore-cursor-color 'after-insert-mode))
  171. (if (and (memq this-command '(dabbrev-expand hippie-expand))
  172. (markerp viper-insert-point)
  173. (marker-position viper-insert-point))
  174. (setq viper-pre-command-point (marker-position viper-insert-point))))
  175. (defun viper-R-state-post-command-sentinel ()
  176. ;; Restoring cursor color is needed despite
  177. ;; viper-replace-state-pre-command-sentinel: When you jump to another buffer
  178. ;; in another frame, the pre-command hook won't change cursor color to
  179. ;; default in that other frame. So, if the second frame cursor was red and
  180. ;; we set the point outside the replacement region, then the cursor color
  181. ;; will remain red. Restoring the default, below, prevents this.
  182. (if (and (<= (viper-replace-start) (point))
  183. (<= (point) (viper-replace-end)))
  184. (viper-change-cursor-color
  185. (viper-frame-value viper-replace-overlay-cursor-color))
  186. (viper-restore-cursor-color 'after-replace-mode)))
  187. ;; to speed up, don't change cursor color before self-insert
  188. ;; and common move commands
  189. (defsubst viper-replace-state-pre-command-sentinel ()
  190. (or (viper-preserve-cursor-color)
  191. (viper-restore-cursor-color 'after-replace-mode)))
  192. ;; Make sure we don't delete more than needed.
  193. ;; This is executed at viper-last-posn-in-replace-region
  194. (defsubst viper-trim-replace-chars-to-delete-if-necessary ()
  195. (setq viper-replace-chars-to-delete
  196. (max 0
  197. (min viper-replace-chars-to-delete
  198. ;; Don't delete more than to the end of repl overlay
  199. (viper-chars-in-region
  200. (viper-replace-end) viper-last-posn-in-replace-region)
  201. ;; point is viper-last-posn-in-replace-region now
  202. ;; So, this limits deletion to the end of line
  203. (viper-chars-in-region (point) (viper-line-pos 'end))
  204. ))))
  205. (defun viper-replace-state-post-command-sentinel ()
  206. ;; Restoring cursor color is needed despite
  207. ;; viper-replace-state-pre-command-sentinel: When one jumps to another buffer
  208. ;; in another frame, the pre-command hook won't change cursor color to
  209. ;; default in that other frame. So, if the second frame cursor was red and
  210. ;; we set the point outside the replacement region, then the cursor color
  211. ;; will remain red. Restoring the default, below, fixes this problem.
  212. ;;
  213. ;; We optimize for some commands, like self-insert-command,
  214. ;; viper-delete-backward-char, etc., since they either don't change
  215. ;; cursor color or, if they terminate replace mode, the color will be changed
  216. ;; in viper-finish-change
  217. (or (viper-preserve-cursor-color)
  218. (viper-restore-cursor-color 'after-replace-mode))
  219. (cond
  220. ((eq viper-current-state 'replace-state)
  221. ;; delete characters to compensate for inserted chars.
  222. (let ((replace-boundary (viper-replace-end)))
  223. (save-excursion
  224. (goto-char viper-last-posn-in-replace-region)
  225. (viper-trim-replace-chars-to-delete-if-necessary)
  226. (delete-char viper-replace-chars-to-delete)
  227. (setq viper-replace-chars-to-delete 0)
  228. ;; terminate replace mode if reached replace limit
  229. (if (= viper-last-posn-in-replace-region (viper-replace-end))
  230. (viper-finish-change)))
  231. (when (viper-pos-within-region
  232. (point) (viper-replace-start) replace-boundary)
  233. ;; the state may have changed in viper-finish-change above
  234. (if (eq viper-current-state 'replace-state)
  235. (viper-change-cursor-color
  236. (viper-frame-value viper-replace-overlay-cursor-color)))
  237. (setq viper-last-posn-in-replace-region (point-marker)))))
  238. ;; terminate replace mode if changed Viper states.
  239. (t (viper-finish-change))))
  240. ;; changing mode
  241. ;; Change state to NEW-STATE---either emacs-state, vi-state, or insert-state.
  242. (defun viper-change-state (new-state)
  243. ;; Keep viper-post/pre-command-hooks fresh.
  244. ;; We remove then add viper-post/pre-command-sentinel since it is very
  245. ;; desirable that viper-pre-command-sentinel is the last hook and
  246. ;; viper-post-command-sentinel is the first hook.
  247. (when (featurep 'xemacs)
  248. (make-local-hook 'viper-after-change-functions)
  249. (make-local-hook 'viper-before-change-functions)
  250. (make-local-hook 'viper-post-command-hooks)
  251. (make-local-hook 'viper-pre-command-hooks))
  252. (remove-hook 'post-command-hook 'viper-post-command-sentinel)
  253. (add-hook 'post-command-hook 'viper-post-command-sentinel)
  254. (remove-hook 'pre-command-hook 'viper-pre-command-sentinel)
  255. (add-hook 'pre-command-hook 'viper-pre-command-sentinel t)
  256. ;; These hooks will be added back if switching to insert/replace mode
  257. (remove-hook 'viper-post-command-hooks
  258. 'viper-insert-state-post-command-sentinel 'local)
  259. (remove-hook 'viper-pre-command-hooks
  260. 'viper-insert-state-pre-command-sentinel 'local)
  261. (setq viper-intermediate-command nil)
  262. (cond ((eq new-state 'vi-state)
  263. (cond ((member viper-current-state '(insert-state replace-state))
  264. ;; move viper-last-posn-while-in-insert-state
  265. ;; This is a normal hook that is executed in insert/replace
  266. ;; states after each command. In Vi/Emacs state, it does
  267. ;; nothing. We need to execute it here to make sure that
  268. ;; the last posn was recorded when we hit ESC.
  269. ;; It may be left unrecorded if the last thing done in
  270. ;; insert/repl state was dabbrev-expansion or abbrev
  271. ;; expansion caused by hitting ESC
  272. (viper-insert-state-post-command-sentinel)
  273. (condition-case conds
  274. (progn
  275. (viper-save-last-insertion
  276. viper-insert-point
  277. viper-last-posn-while-in-insert-state)
  278. (if viper-began-as-replace
  279. (setq viper-began-as-replace nil)
  280. ;; repeat insert commands if numerical arg > 1
  281. (save-excursion
  282. (viper-repeat-insert-command))))
  283. (error
  284. (viper-message-conditions conds)))
  285. (if (> (length viper-last-insertion) 0)
  286. (viper-push-onto-ring viper-last-insertion
  287. 'viper-insertion-ring))
  288. (if viper-ESC-moves-cursor-back
  289. (or (bolp) (viper-beginning-of-field) (backward-char 1))))
  290. ))
  291. ;; insert or replace
  292. ((memq new-state '(insert-state replace-state))
  293. (if (memq viper-current-state '(emacs-state vi-state))
  294. (viper-move-marker-locally 'viper-insert-point (point)))
  295. (viper-move-marker-locally
  296. 'viper-last-posn-while-in-insert-state (point))
  297. (add-hook 'viper-post-command-hooks
  298. 'viper-insert-state-post-command-sentinel t 'local)
  299. (add-hook 'viper-pre-command-hooks
  300. 'viper-insert-state-pre-command-sentinel t 'local))
  301. ) ; outermost cond
  302. ;; Nothing needs to be done to switch to emacs mode! Just set some
  303. ;; variables, which is already done in viper-change-state-to-emacs!
  304. ;; ISO accents
  305. ;; always turn off iso-accents-mode in vi-state, or else we won't be able to
  306. ;; use the keys `,',^ , as they will do accents instead of Vi actions.
  307. (cond ((eq new-state 'vi-state) (viper-set-iso-accents-mode nil));accents off
  308. (viper-automatic-iso-accents (viper-set-iso-accents-mode t));accents on
  309. (t (viper-set-iso-accents-mode nil)))
  310. ;; Always turn off quail mode in vi state
  311. (cond ((eq new-state 'vi-state) (viper-set-input-method nil)) ;intl input off
  312. (viper-special-input-method (viper-set-input-method t)) ;intl input on
  313. (t (viper-set-input-method nil)))
  314. (setq viper-current-state new-state)
  315. (viper-update-syntax-classes)
  316. (viper-normalize-minor-mode-map-alist)
  317. (viper-adjust-keys-for new-state)
  318. (viper-set-mode-vars-for new-state)
  319. (viper-refresh-mode-line)
  320. )
  321. (defun viper-adjust-keys-for (state)
  322. "Make necessary adjustments to keymaps before entering STATE."
  323. (cond ((memq state '(insert-state replace-state))
  324. (if viper-auto-indent
  325. (progn
  326. (define-key viper-insert-basic-map "\C-m" 'viper-autoindent)
  327. (if viper-want-emacs-keys-in-insert
  328. ;; expert
  329. (define-key viper-insert-basic-map "\C-j" nil)
  330. ;; novice
  331. (define-key viper-insert-basic-map "\C-j" 'viper-autoindent)))
  332. (define-key viper-insert-basic-map "\C-m" nil)
  333. (define-key viper-insert-basic-map "\C-j" nil))
  334. (setq viper-insert-diehard-minor-mode
  335. (not viper-want-emacs-keys-in-insert))
  336. (if viper-want-ctl-h-help
  337. (progn
  338. (define-key viper-insert-basic-map "\C-h" 'help-command)
  339. (define-key viper-replace-map "\C-h" 'help-command))
  340. (define-key viper-insert-basic-map
  341. "\C-h" 'viper-del-backward-char-in-insert)
  342. (define-key viper-replace-map
  343. "\C-h" 'viper-del-backward-char-in-replace))
  344. ;; In XEmacs, C-h overrides backspace, so we make sure it doesn't.
  345. (define-key viper-insert-basic-map
  346. [backspace] 'viper-del-backward-char-in-insert)
  347. (define-key viper-replace-map
  348. [backspace] 'viper-del-backward-char-in-replace)
  349. ) ; end insert/replace case
  350. (t ; Vi state
  351. (setq viper-vi-diehard-minor-mode (not viper-want-emacs-keys-in-vi))
  352. (if viper-want-ctl-h-help
  353. (define-key viper-vi-basic-map "\C-h" 'help-command)
  354. (define-key viper-vi-basic-map "\C-h" 'viper-backward-char))
  355. ;; In XEmacs, C-h overrides backspace, so we make sure it doesn't.
  356. (define-key viper-vi-basic-map [backspace] 'viper-backward-char))
  357. ))
  358. ;; Normalizes minor-mode-map-alist by putting Viper keymaps first.
  359. ;; This ensures that Viper bindings are in effect, regardless of which minor
  360. ;; modes were turned on by the user or by other packages.
  361. (defun viper-normalize-minor-mode-map-alist ()
  362. (setq viper--intercept-key-maps
  363. (list
  364. (cons 'viper-vi-intercept-minor-mode viper-vi-intercept-map)
  365. (cons 'viper-insert-intercept-minor-mode viper-insert-intercept-map)
  366. (cons 'viper-emacs-intercept-minor-mode viper-emacs-intercept-map)
  367. ))
  368. (setq viper--key-maps
  369. (list (cons 'viper-vi-minibuffer-minor-mode viper-minibuffer-map)
  370. (cons 'viper-vi-local-user-minor-mode viper-vi-local-user-map)
  371. (cons 'viper-vi-kbd-minor-mode viper-vi-kbd-map)
  372. (cons 'viper-vi-global-user-minor-mode viper-vi-global-user-map)
  373. (cons 'viper-vi-state-modifier-minor-mode
  374. (if (keymapp
  375. (cdr (assoc major-mode viper-vi-state-modifier-alist)))
  376. (cdr (assoc major-mode viper-vi-state-modifier-alist))
  377. viper-empty-keymap))
  378. (cons 'viper-vi-diehard-minor-mode viper-vi-diehard-map)
  379. (cons 'viper-vi-basic-minor-mode viper-vi-basic-map)
  380. (cons 'viper-replace-minor-mode viper-replace-map)
  381. ;; viper-insert-minibuffer-minor-mode must come after
  382. ;; viper-replace-minor-mode
  383. (cons 'viper-insert-minibuffer-minor-mode
  384. viper-minibuffer-map)
  385. (cons 'viper-insert-local-user-minor-mode
  386. viper-insert-local-user-map)
  387. (cons 'viper-insert-kbd-minor-mode viper-insert-kbd-map)
  388. (cons 'viper-insert-global-user-minor-mode
  389. viper-insert-global-user-map)
  390. (cons 'viper-insert-state-modifier-minor-mode
  391. (if (keymapp
  392. (cdr (assoc major-mode
  393. viper-insert-state-modifier-alist)))
  394. (cdr (assoc major-mode
  395. viper-insert-state-modifier-alist))
  396. viper-empty-keymap))
  397. (cons 'viper-insert-diehard-minor-mode viper-insert-diehard-map)
  398. (cons 'viper-insert-basic-minor-mode viper-insert-basic-map)
  399. (cons 'viper-emacs-local-user-minor-mode
  400. viper-emacs-local-user-map)
  401. (cons 'viper-emacs-kbd-minor-mode viper-emacs-kbd-map)
  402. (cons 'viper-emacs-global-user-minor-mode
  403. viper-emacs-global-user-map)
  404. (cons 'viper-emacs-state-modifier-minor-mode
  405. (if (keymapp
  406. (cdr
  407. (assoc major-mode viper-emacs-state-modifier-alist)))
  408. (cdr
  409. (assoc major-mode viper-emacs-state-modifier-alist))
  410. viper-empty-keymap))
  411. ))
  412. ;; This var is not local in Emacs, so we make it local. It must be local
  413. ;; because although the stack of minor modes can be the same for all buffers,
  414. ;; the associated *keymaps* can be different. In Viper,
  415. ;; viper-vi-local-user-map, viper-insert-local-user-map, and others can have
  416. ;; different keymaps for different buffers. Also, the keymaps associated
  417. ;; with viper-vi/insert-state-modifier-minor-mode can be different.
  418. ;; ***This is needed only in case emulation-mode-map-alists is not defined.
  419. ;; In emacs with emulation-mode-map-alists, nothing needs to be done
  420. (unless
  421. (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
  422. (set (make-local-variable 'minor-mode-map-alist)
  423. (viper-append-filter-alist
  424. (append viper--intercept-key-maps viper--key-maps)
  425. minor-mode-map-alist)))
  426. )
  427. ;; Viper mode-changing commands and utilities
  428. ;; Modifies mode-line-buffer-identification.
  429. (defun viper-refresh-mode-line ()
  430. (set (make-local-variable 'viper-mode-string)
  431. (cond ((eq viper-current-state 'emacs-state) viper-emacs-state-id)
  432. ((eq viper-current-state 'vi-state) viper-vi-state-id)
  433. ((eq viper-current-state 'replace-state) viper-replace-state-id)
  434. ((eq viper-current-state 'insert-state) viper-insert-state-id)))
  435. ;; Sets Viper mode string in global-mode-string
  436. (force-mode-line-update))
  437. ;; Switch from Insert state to Vi state.
  438. (defun viper-exit-insert-state ()
  439. (interactive)
  440. (viper-change-state-to-vi))
  441. (defun viper-set-mode-vars-for (state)
  442. "Sets Viper minor mode variables to put Viper's state STATE in effect."
  443. ;; Emacs state
  444. (setq viper-vi-minibuffer-minor-mode nil
  445. viper-insert-minibuffer-minor-mode nil
  446. viper-vi-intercept-minor-mode nil
  447. viper-insert-intercept-minor-mode nil
  448. viper-vi-local-user-minor-mode nil
  449. viper-vi-kbd-minor-mode nil
  450. viper-vi-global-user-minor-mode nil
  451. viper-vi-state-modifier-minor-mode nil
  452. viper-vi-diehard-minor-mode nil
  453. viper-vi-basic-minor-mode nil
  454. viper-replace-minor-mode nil
  455. viper-insert-local-user-minor-mode nil
  456. viper-insert-kbd-minor-mode nil
  457. viper-insert-global-user-minor-mode nil
  458. viper-insert-state-modifier-minor-mode nil
  459. viper-insert-diehard-minor-mode nil
  460. viper-insert-basic-minor-mode nil
  461. viper-emacs-intercept-minor-mode t
  462. viper-emacs-local-user-minor-mode t
  463. viper-emacs-kbd-minor-mode (not (viper-is-in-minibuffer))
  464. viper-emacs-global-user-minor-mode t
  465. viper-emacs-state-modifier-minor-mode t
  466. )
  467. ;; Vi state
  468. (if (eq state 'vi-state) ; adjust for vi-state
  469. (setq
  470. viper-vi-intercept-minor-mode t
  471. viper-vi-minibuffer-minor-mode (viper-is-in-minibuffer)
  472. viper-vi-local-user-minor-mode t
  473. viper-vi-kbd-minor-mode (not (viper-is-in-minibuffer))
  474. viper-vi-global-user-minor-mode t
  475. viper-vi-state-modifier-minor-mode t
  476. ;; don't let the diehard keymap block command completion
  477. ;; and other things in the minibuffer
  478. viper-vi-diehard-minor-mode (not
  479. (or viper-want-emacs-keys-in-vi
  480. (viper-is-in-minibuffer)))
  481. viper-vi-basic-minor-mode t
  482. viper-emacs-intercept-minor-mode nil
  483. viper-emacs-local-user-minor-mode nil
  484. viper-emacs-kbd-minor-mode nil
  485. viper-emacs-global-user-minor-mode nil
  486. viper-emacs-state-modifier-minor-mode nil
  487. ))
  488. ;; Insert and Replace states
  489. (if (member state '(insert-state replace-state))
  490. (setq
  491. viper-insert-intercept-minor-mode t
  492. viper-replace-minor-mode (eq state 'replace-state)
  493. viper-insert-minibuffer-minor-mode (viper-is-in-minibuffer)
  494. viper-insert-local-user-minor-mode t
  495. viper-insert-kbd-minor-mode (not (viper-is-in-minibuffer))
  496. viper-insert-global-user-minor-mode t
  497. viper-insert-state-modifier-minor-mode t
  498. ;; don't let the diehard keymap block command completion
  499. ;; and other things in the minibuffer
  500. viper-insert-diehard-minor-mode (not
  501. (or
  502. viper-want-emacs-keys-in-insert
  503. (viper-is-in-minibuffer)))
  504. viper-insert-basic-minor-mode t
  505. viper-emacs-intercept-minor-mode nil
  506. viper-emacs-local-user-minor-mode nil
  507. viper-emacs-kbd-minor-mode nil
  508. viper-emacs-global-user-minor-mode nil
  509. viper-emacs-state-modifier-minor-mode nil
  510. ))
  511. ;; minibuffer faces
  512. (if (viper-has-face-support-p)
  513. (setq viper-minibuffer-current-face
  514. (cond ((eq state 'emacs-state) viper-minibuffer-emacs-face)
  515. ((eq state 'vi-state) viper-minibuffer-vi-face)
  516. ((memq state '(insert-state replace-state))
  517. viper-minibuffer-insert-face))))
  518. (if (viper-is-in-minibuffer)
  519. (viper-set-minibuffer-overlay))
  520. )
  521. ;; This also takes care of the annoying incomplete lines in files.
  522. ;; Also, this fixes `undo' to work vi-style for complex commands.
  523. (defun viper-change-state-to-vi ()
  524. "Change Viper state to Vi."
  525. (interactive)
  526. (if (and viper-first-time (not (viper-is-in-minibuffer)))
  527. (viper-mode)
  528. (if overwrite-mode (overwrite-mode -1))
  529. (or (viper-overlay-p viper-replace-overlay)
  530. (viper-set-replace-overlay (point-min) (point-min)))
  531. (viper-hide-replace-overlay)
  532. ;; Expand abbrevs iff the previous character has word syntax.
  533. (and abbrev-mode
  534. (eq (char-syntax (preceding-char)) ?w)
  535. (expand-abbrev))
  536. (if (and auto-fill-function (> (current-column) fill-column))
  537. (funcall auto-fill-function))
  538. ;; don't leave whitespace lines around
  539. (if (and (memq last-command
  540. '(viper-autoindent
  541. viper-open-line viper-Open-line
  542. viper-replace-state-exit-cmd))
  543. (viper-over-whitespace-line))
  544. (indent-to-left-margin))
  545. (viper-add-newline-at-eob-if-necessary)
  546. (viper-adjust-undo)
  547. (if (eq viper-current-state 'emacs-state)
  548. (viper-restore-cursor-color 'after-emacs-mode)
  549. (viper-restore-cursor-color 'after-insert-mode))
  550. (viper-change-state 'vi-state)
  551. ;; Protect against user errors in hooks
  552. (condition-case conds
  553. (run-hooks 'viper-vi-state-hook)
  554. (error
  555. (viper-message-conditions conds)))))
  556. (defun viper-change-state-to-insert ()
  557. "Change Viper state to Insert."
  558. (interactive)
  559. (viper-change-state 'insert-state)
  560. (or (viper-overlay-p viper-replace-overlay)
  561. (viper-set-replace-overlay (point-min) (point-min)))
  562. (viper-hide-replace-overlay)
  563. (let ((icolor (viper-frame-value viper-insert-state-cursor-color)))
  564. (or (stringp (viper-get-saved-cursor-color-in-insert-mode))
  565. (string= (viper-get-cursor-color) icolor)
  566. (viper-save-cursor-color 'before-insert-mode))
  567. (viper-change-cursor-color icolor))
  568. ;; Protect against user errors in hooks
  569. (condition-case conds
  570. (run-hooks 'viper-insert-state-hook)
  571. (error
  572. (viper-message-conditions conds))))
  573. (defsubst viper-downgrade-to-insert ()
  574. ;; Protect against user errors in hooks
  575. (condition-case conds
  576. (run-hooks 'viper-insert-state-hook)
  577. (error
  578. (viper-message-conditions conds)))
  579. (setq viper-current-state 'insert-state
  580. viper-replace-minor-mode nil))
  581. ;; Change to replace state. When the end of replacement region is reached,
  582. ;; replace state changes to insert state.
  583. (defun viper-change-state-to-replace (&optional non-R-cmd)
  584. (viper-change-state 'replace-state)
  585. ;; Run insert-state-hook
  586. (condition-case conds
  587. (run-hooks 'viper-insert-state-hook 'viper-replace-state-hook)
  588. (error
  589. (viper-message-conditions conds)))
  590. (if non-R-cmd
  591. (viper-start-replace)
  592. ;; 'R' is implemented using Emacs's overwrite-mode
  593. (viper-start-R-mode))
  594. )
  595. (defun viper-change-state-to-emacs ()
  596. "Change Viper state to Emacs."
  597. (interactive)
  598. (or (viper-overlay-p viper-replace-overlay)
  599. (viper-set-replace-overlay (point-min) (point-min)))
  600. (viper-hide-replace-overlay)
  601. (let ((ecolor (viper-frame-value viper-emacs-state-cursor-color)))
  602. (when ecolor
  603. (or (stringp (viper-get-saved-cursor-color-in-emacs-mode))
  604. (string= (viper-get-cursor-color) ecolor)
  605. (viper-save-cursor-color 'before-emacs-mode))
  606. (viper-change-cursor-color ecolor)))
  607. (viper-change-state 'emacs-state)
  608. ;; Protect against user errors in hooks
  609. (condition-case conds
  610. (run-hooks 'viper-emacs-state-hook)
  611. (error
  612. (viper-message-conditions conds))))
  613. ;; escape to emacs mode temporarily
  614. (defun viper-escape-to-emacs (arg &optional events)
  615. "Escape to Emacs state from Vi state for one Emacs command.
  616. ARG is used as the prefix value for the executed command. If
  617. EVENTS is a list of events, which become the beginning of the command."
  618. (interactive "P")
  619. (if (viper= (viper-last-command-char) ?\\)
  620. (message "Switched to EMACS state for the next command..."))
  621. (viper-escape-to-state arg events 'emacs-state))
  622. ;; escape to Vi mode temporarily
  623. (defun viper-escape-to-vi (arg)
  624. "Escape from Emacs state to Vi state for one Vi 1-character command.
  625. If the Vi command that the user types has a prefix argument, e.g., `d2w', then
  626. Vi's prefix argument will be used. Otherwise, the prefix argument passed to
  627. `viper-escape-to-vi' is used."
  628. (interactive "P")
  629. (message "Switched to VI state for the next command...")
  630. (viper-escape-to-state arg nil 'vi-state))
  631. ;; Escape to STATE mode for one Emacs command.
  632. (defun viper-escape-to-state (arg events state)
  633. ;;(let (com key prefix-arg)
  634. (let (com key)
  635. ;; this temporarily turns off Viper's minor mode keymaps
  636. (viper-set-mode-vars-for state)
  637. (viper-normalize-minor-mode-map-alist)
  638. (if events (viper-set-unread-command-events events))
  639. ;; protect against keyboard quit and other errors
  640. (condition-case nil
  641. (let (viper-vi-kbd-minor-mode
  642. viper-insert-kbd-minor-mode
  643. viper-emacs-kbd-minor-mode)
  644. (unwind-protect
  645. (progn
  646. (setq com
  647. (key-binding (setq key (viper-read-key-sequence nil))))
  648. ;; In case of binding indirection--chase definitions.
  649. ;; Have to do it here because we execute this command under
  650. ;; different keymaps, so command-execute may not do the
  651. ;; right thing there
  652. (while (vectorp com) (setq com (key-binding com))))
  653. nil)
  654. ;; Execute command com in the original Viper state, not in state
  655. ;; `state'. Otherwise, if we switch buffers while executing the
  656. ;; escaped to command, Viper's mode vars will remain those of
  657. ;; `state'. When we return to the orig buffer, the bindings will be
  658. ;; screwed up.
  659. (viper-set-mode-vars-for viper-current-state)
  660. ;; this-command, last-command-char, last-command-event
  661. (setq this-command com)
  662. (if (featurep 'xemacs)
  663. ;; XEmacs represents key sequences as vectors
  664. (setq last-command-event
  665. (viper-copy-event (viper-seq-last-elt key))
  666. last-command-char (event-to-character last-command-event))
  667. ;; Emacs represents them as sequences (str or vec)
  668. (setq last-command-event
  669. (viper-copy-event (viper-seq-last-elt key))))
  670. (if (commandp com)
  671. ;; pretend that current state is the state we escaped to
  672. (let ((viper-current-state state))
  673. (setq prefix-arg (or prefix-arg arg))
  674. (command-execute com)))
  675. )
  676. (quit (ding))
  677. (error (beep 1))))
  678. ;; set state in the new buffer
  679. (viper-set-mode-vars-for viper-current-state))
  680. ;; This is used in order to allow reading characters according to the input
  681. ;; method. The character is read in emacs and inserted into the buffer.
  682. ;; If an input method is in effect, this might
  683. ;; cause several characters to be combined into one.
  684. ;; Also takes care of the iso-accents mode
  685. (defun viper-special-read-and-insert-char ()
  686. (viper-set-mode-vars-for 'emacs-state)
  687. (viper-normalize-minor-mode-map-alist)
  688. (if viper-special-input-method
  689. (viper-set-input-method t))
  690. (if viper-automatic-iso-accents
  691. (viper-set-iso-accents-mode t))
  692. (condition-case nil
  693. (let (viper-vi-kbd-minor-mode
  694. viper-insert-kbd-minor-mode
  695. viper-emacs-kbd-minor-mode
  696. ch)
  697. (cond ((and viper-special-input-method
  698. (featurep 'emacs)
  699. (fboundp 'quail-input-method))
  700. ;; (let ...) is used to restore unread-command-events to the
  701. ;; original state. We don't want anything left in there after
  702. ;; key translation. (Such left-overs are possible if the user
  703. ;; types a regular key.)
  704. (let (unread-command-events)
  705. ;; The next cmd and viper-set-unread-command-events
  706. ;; are intended to prevent the input method
  707. ;; from swallowing ^M, ^Q and other special characters
  708. (setq ch (read-char-exclusive))
  709. ;; replace ^M with the newline
  710. (if (eq ch ?\C-m) (setq ch ?\n))
  711. ;; Make sure ^V and ^Q work as quotation chars
  712. (if (memq ch '(?\C-v ?\C-q))
  713. (setq ch (read-char-exclusive)))
  714. (viper-set-unread-command-events ch)
  715. (quail-input-method nil)
  716. (if (and ch (string= quail-current-str ""))
  717. (insert ch)
  718. (insert quail-current-str))
  719. (setq ch (or ch
  720. (aref quail-current-str
  721. (1- (length quail-current-str)))))
  722. ))
  723. ((and viper-special-input-method
  724. (featurep 'xemacs)
  725. (fboundp 'quail-start-translation))
  726. ;; same as above but for XEmacs, which doesn't have
  727. ;; quail-input-method
  728. (let (unread-command-events)
  729. (setq ch (read-char-exclusive))
  730. ;; replace ^M with the newline
  731. (if (eq ch ?\C-m) (setq ch ?\n))
  732. ;; Make sure ^V and ^Q work as quotation chars
  733. (if (memq ch '(?\C-v ?\C-q))
  734. (setq ch (read-char-exclusive)))
  735. (viper-set-unread-command-events ch)
  736. (quail-start-translation nil)
  737. (if (and ch (string= quail-current-str ""))
  738. (insert ch)
  739. (insert quail-current-str))
  740. (setq ch (or ch
  741. (aref quail-current-str
  742. (1- (length quail-current-str)))))
  743. ))
  744. ((and (boundp 'iso-accents-mode) iso-accents-mode)
  745. (setq ch (aref (read-key-sequence nil) 0))
  746. ;; replace ^M with the newline
  747. (if (eq ch ?\C-m) (setq ch ?\n))
  748. ;; Make sure ^V and ^Q work as quotation chars
  749. (if (memq ch '(?\C-v ?\C-q))
  750. (setq ch (aref (read-key-sequence nil) 0)))
  751. (insert ch))
  752. (t
  753. ;;(setq ch (read-char-exclusive))
  754. (setq ch (aref (read-key-sequence nil) 0))
  755. (if (featurep 'xemacs)
  756. (setq ch (event-to-character ch)))
  757. ;; replace ^M with the newline
  758. (if (eq ch ?\C-m) (setq ch ?\n))
  759. ;; Make sure ^V and ^Q work as quotation chars
  760. (if (memq ch '(?\C-v ?\C-q))
  761. (progn
  762. ;;(setq ch (read-char-exclusive))
  763. (setq ch (aref (read-key-sequence nil) 0))
  764. (if (featurep 'xemacs)
  765. (setq ch (event-to-character ch))))
  766. )
  767. (insert ch))
  768. )
  769. (setq last-command-event
  770. (viper-copy-event (if (featurep 'xemacs)
  771. (character-to-event ch) ch)))
  772. ) ; let
  773. (error nil)
  774. ) ; condition-case
  775. (viper-set-input-method nil)
  776. (viper-set-iso-accents-mode nil)
  777. (viper-set-mode-vars-for viper-current-state)
  778. )
  779. (defun viper-exec-form-in-vi (form)
  780. "Execute FORM in Vi state, regardless of the current Vi state."
  781. (let ((buff (current-buffer))
  782. result)
  783. (viper-set-mode-vars-for 'vi-state)
  784. (condition-case nil
  785. (let (viper-vi-kbd-minor-mode) ; execute without kbd macros
  786. (setq result (eval form)))
  787. (error
  788. (signal 'quit nil)))
  789. (if (not (equal buff (current-buffer))) ; cmd switched buffer
  790. (with-current-buffer buff
  791. (viper-set-mode-vars-for viper-current-state)))
  792. (viper-set-mode-vars-for viper-current-state)
  793. result))
  794. (defun viper-exec-form-in-emacs (form)
  795. "Execute FORM in Emacs, temporarily disabling Viper's minor modes.
  796. Similar to `viper-escape-to-emacs', but accepts forms rather than keystrokes."
  797. (let ((buff (current-buffer))
  798. result)
  799. (viper-set-mode-vars-for 'emacs-state)
  800. (setq result (eval form))
  801. (if (not (equal buff (current-buffer))) ; cmd switched buffer
  802. (with-current-buffer buff
  803. (viper-set-mode-vars-for viper-current-state)))
  804. (viper-set-mode-vars-for viper-current-state)
  805. result))
  806. ;; This executes the last kbd event in emacs mode. Is used when we want to
  807. ;; interpret certain keys directly in emacs (as, for example, in comint mode).
  808. (defun viper-exec-key-in-emacs (arg)
  809. (interactive "P")
  810. (viper-escape-to-emacs arg last-command-event))
  811. ;; This is needed because minor modes sometimes override essential Viper
  812. ;; bindings. By letting Viper know which files these modes are in, it will
  813. ;; arrange to reorganize minor-mode-map-alist so that things will work right.
  814. (defun viper-harness-minor-mode (load-file)
  815. "Familiarize Viper with a minor mode defined in LOAD-FILE.
  816. Minor modes that have their own keymaps may overshadow Viper keymaps.
  817. This function is designed to make Viper aware of the packages that define
  818. such minor modes.
  819. Usage:
  820. (viper-harness-minor-mode load-file)
  821. LOAD-FILE is the name of the file where the specific minor mode is defined.
  822. Suffixes such as .el or .elc should be stripped."
  823. (interactive "sEnter name of the load file: ")
  824. (eval-after-load load-file '(viper-normalize-minor-mode-map-alist))
  825. ;; Change the default for minor-mode-map-alist each time a harnessed minor
  826. ;; mode adds its own keymap to the a-list.
  827. (unless
  828. (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
  829. (eval-after-load
  830. load-file '(setq-default minor-mode-map-alist minor-mode-map-alist)))
  831. )
  832. (defun viper-ESC (arg)
  833. "Emulate ESC key in Emacs.
  834. Prevents multiple escape keystrokes if viper-no-multiple-ESC is true.
  835. If viper-no-multiple-ESC is 'twice double ESC would ding in vi-state.
  836. Other ESC sequences are emulated via the current Emacs's major mode
  837. keymap. This is more convenient on TTYs, since this won't block
  838. function keys such as up, down, etc. ESC will also will also work as
  839. a Meta key in this case. When viper-no-multiple-ESC is nil, ESC works
  840. as a Meta key and any number of multiple escapes are allowed."
  841. (interactive "P")
  842. (let (char)
  843. (cond ((and (not viper-no-multiple-ESC) (eq viper-current-state 'vi-state))
  844. (setq char (viper-read-char-exclusive))
  845. (viper-escape-to-emacs arg (list ?\e char) ))
  846. ((and (eq viper-no-multiple-ESC 'twice)
  847. (eq viper-current-state 'vi-state))
  848. (setq char (viper-read-char-exclusive))
  849. (if (= char (string-to-char viper-ESC-key))
  850. (ding)
  851. (viper-escape-to-emacs arg (list ?\e char) )))
  852. (t (ding)))
  853. ))
  854. (defun viper-alternate-Meta-key (arg)
  855. "Simulate Emacs Meta key."
  856. (interactive "P")
  857. (sit-for 1) (message "ESC-")
  858. (viper-escape-to-emacs arg '(?\e)))
  859. (defun viper-toggle-key-action ()
  860. "Action bound to `viper-toggle-key'."
  861. (interactive)
  862. (if (and (< viper-expert-level 2) (equal viper-toggle-key "\C-z"))
  863. (if (viper-window-display-p)
  864. (viper-iconify)
  865. (suspend-emacs))
  866. (viper-change-state-to-emacs)))
  867. ;; Intercept ESC sequences on dumb terminals.
  868. ;; Based on the idea contributed by Marcelino Veiga Tuimil <mveiga@dit.upm.es>
  869. ;; Check if last key was ESC and if so try to reread it as a function key.
  870. ;; But only if there are characters to read during a very short time.
  871. ;; Returns the last event, if any.
  872. (defun viper-envelop-ESC-key ()
  873. (let ((event last-input-event)
  874. (keyseq [nil])
  875. (inhibit-quit t))
  876. (if (viper-ESC-event-p event)
  877. (progn
  878. ;; Some versions of Emacs (eg., 22.50.8 have a bug, which makes even
  879. ;; a single ESC into ;; a fast keyseq. To guard against this, we
  880. ;; added a check if there are other events as well. Keep the next
  881. ;; line for the next time the bug reappears, so that will remember to
  882. ;; report it.
  883. ;;(if (and (viper-fast-keysequence-p) unread-command-events)
  884. (if (viper-fast-keysequence-p) ;; for Emacsen without the above bug
  885. (progn
  886. (let (minor-mode-map-alist emulation-mode-map-alists)
  887. (viper-set-unread-command-events event)
  888. (setq keyseq (read-key-sequence nil 'continue-echo))
  889. ) ; let
  890. ;; If keyseq translates into something that still has ESC
  891. ;; at the beginning, separate ESC from the rest of the seq.
  892. ;; In XEmacs we check for events that are keypress meta-key
  893. ;; and convert them into [escape key]
  894. ;;
  895. ;; This is needed for the following reason:
  896. ;; If ESC is the first symbol, we interpret it as if the
  897. ;; user typed ESC and then quickly some other symbols.
  898. ;; If ESC is not the first one, then the key sequence
  899. ;; entered was apparently translated into a function key or
  900. ;; something (e.g., one may have
  901. ;; (define-key function-key-map "\e[192z" [f11])
  902. ;; which would translate the escape-sequence generated by
  903. ;; f11 in an xterm window into the symbolic key f11.
  904. ;;
  905. ;; If `first-key' is not an ESC event, we make it into the
  906. ;; last-command-event in order to pretend that this key was
  907. ;; pressed. This is needed to allow arrow keys to be bound to
  908. ;; macros. Otherwise, viper-exec-mapped-kbd-macro will think
  909. ;; that the last event was ESC and so it'll execute whatever is
  910. ;; bound to ESC. (Viper macros can't be bound to
  911. ;; ESC-sequences).
  912. (let* ((first-key (elt keyseq 0))
  913. (key-mod (event-modifiers first-key)))
  914. (cond ((and (viper-ESC-event-p first-key)
  915. (not (viper-translate-all-ESC-keysequences)))
  916. ;; put keys following ESC on the unread list
  917. ;; and return ESC as the key-sequence
  918. (viper-set-unread-command-events (viper-subseq keyseq 1))
  919. (setq last-input-event event
  920. keyseq (if (featurep 'emacs)
  921. "\e"
  922. (vector (character-to-event ?\e)))))
  923. ((and (featurep 'xemacs)
  924. (key-press-event-p first-key)
  925. (equal '(meta) key-mod))
  926. (viper-set-unread-command-events
  927. (vconcat (vector
  928. (character-to-event (event-key first-key)))
  929. (viper-subseq keyseq 1)))
  930. (setq last-input-event event
  931. keyseq (vector (character-to-event ?\e))))
  932. ((eventp first-key)
  933. (setq last-command-event
  934. (viper-copy-event first-key)))
  935. ))
  936. ) ; end progn
  937. ;; this is escape event with nothing after it
  938. ;; put in unread-command-event and then re-read
  939. (viper-set-unread-command-events event)
  940. (setq keyseq (read-key-sequence nil))
  941. ))
  942. ;; not an escape event
  943. (setq keyseq (vector event)))
  944. keyseq))
  945. ;; Listen to ESC key.
  946. ;; If a sequence of keys starting with ESC is issued with very short delays,
  947. ;; interpret these keys in Emacs mode, so ESC won't be interpreted as a Vi key.
  948. (defun viper-intercept-ESC-key ()
  949. "Function that implements ESC key in Viper emulation of Vi."
  950. (interactive)
  951. ;; `key-binding' needs to be called in a context where Viper's
  952. ;; minor-mode map(s) have been temporarily disabled so the ESC
  953. ;; binding to viper-intercept-ESC-key doesn't hide the binding we're
  954. ;; looking for (Bug#9146):
  955. (let* ((event (viper-envelop-ESC-key))
  956. (cmd (cond ((equal event viper-ESC-key)
  957. 'viper-intercept-ESC-key)
  958. ((let ((emulation-mode-map-alists nil))
  959. (key-binding event)))
  960. (t
  961. (error "Viper bell")))))
  962. ;; call the actual function to execute ESC (if no other symbols followed)
  963. ;; or the key bound to the ESC sequence (if the sequence was issued
  964. ;; with very short delay between characters).
  965. (if (eq cmd 'viper-intercept-ESC-key)
  966. (setq cmd
  967. (cond ((eq viper-current-state 'vi-state)
  968. 'viper-ESC)
  969. ((eq viper-current-state 'insert-state)
  970. 'viper-exit-insert-state)
  971. ((eq viper-current-state 'replace-state)
  972. 'viper-replace-state-exit-cmd)
  973. (t 'viper-change-state-to-vi)
  974. )))
  975. (call-interactively cmd)))
  976. ;; prefix argument for Vi mode
  977. ;; In Vi mode, prefix argument is a dotted pair (NUM . COM) where NUM
  978. ;; represents the numeric value of the prefix argument and COM represents
  979. ;; command prefix such as "c", "d", "m" and "y".
  980. ;; Get value part of prefix-argument ARG.
  981. (defsubst viper-p-val (arg)
  982. (cond ((null arg) 1)
  983. ((consp arg)
  984. (if (or (null (car arg)) (equal (car arg) '(nil)))
  985. 1 (car arg)))
  986. (t arg)))
  987. ;; Get raw value part of prefix-argument ARG.
  988. (defsubst viper-P-val (arg)
  989. (cond ((consp arg) (car arg))
  990. (t arg)))
  991. ;; Get com part of prefix-argument ARG.
  992. (defsubst viper-getcom (arg)
  993. (cond ((null arg) nil)
  994. ((consp arg) (cdr arg))
  995. (t nil)))
  996. ;; Get com part of prefix-argument ARG and modify it.
  997. (defun viper-getCom (arg)
  998. (let ((com (viper-getcom arg)))
  999. (cond ((viper= com ?c) ?c)
  1000. ;; Previously, ?c was being converted to ?C, but this prevented
  1001. ;; multiline replace regions.
  1002. ;;((viper= com ?c) ?C)
  1003. ((viper= com ?d) ?D)
  1004. ((viper= com ?y) ?Y)
  1005. (t com))))
  1006. ;; Compute numeric prefix arg value.
  1007. ;; Invoked by EVENT-CHAR. COM is the command part obtained so far.
  1008. (defun viper-prefix-arg-value (event-char com)
  1009. (let ((viper-intermediate-command 'viper-digit-argument)
  1010. value func)
  1011. ;; read while number
  1012. (while (and (viper-characterp event-char)
  1013. (>= event-char ?0) (<= event-char ?9))
  1014. (setq value (+ (* (if (integerp value) value 0) 10) (- event-char ?0)))
  1015. (setq event-char (viper-read-event-convert-to-char)))
  1016. (setq prefix-arg value)
  1017. (if com (setq prefix-arg (cons prefix-arg com)))
  1018. (while (eq event-char ?U)
  1019. (viper-describe-arg prefix-arg)
  1020. (setq event-char (viper-read-event-convert-to-char)))
  1021. (if (or com (and (not (eq viper-current-state 'vi-state))
  1022. ;; make sure it is a Vi command
  1023. (viper-characterp event-char)
  1024. (viper-vi-command-p event-char)
  1025. ))
  1026. ;; If appears to be one of the vi commands,
  1027. ;; then execute it with funcall and clear prefix-arg in order to not
  1028. ;; confuse subsequent commands
  1029. (progn
  1030. ;; last-command-event is the char we want emacs to think was typed
  1031. ;; last. If com is not nil, the viper-digit-argument command was
  1032. ;; called from within viper-prefix-arg command, such as `d', `w',
  1033. ;; etc., i.e., the user typed, say, d2. In this case, `com' would be
  1034. ;; `d', `w', etc. If viper-digit-argument was invoked by
  1035. ;; viper-escape-to-vi (which is indicated by the fact that the
  1036. ;; current state is not vi-state), then `event-char' represents the
  1037. ;; vi command to be executed (e.g., `d', `w', etc). Again,
  1038. ;; last-command-event must make emacs believe that this is the command
  1039. ;; we typed.
  1040. (cond ((eq event-char 'return) (setq event-char ?\C-m))
  1041. ((eq event-char 'delete) (setq event-char ?\C-?))
  1042. ((eq event-char 'backspace) (setq event-char ?\C-h))
  1043. ((eq event-char 'space) (setq event-char ?\ )))
  1044. (setq last-command-event
  1045. (if (featurep 'xemacs)
  1046. (character-to-event (or com event-char))
  1047. (or com event-char)))
  1048. (setq func (viper-exec-form-in-vi
  1049. `(key-binding (char-to-string ,event-char))))
  1050. (funcall func prefix-arg)
  1051. (setq prefix-arg nil))
  1052. ;; some other command -- let emacs do it in its own way
  1053. (viper-set-unread-command-events event-char))
  1054. ))
  1055. ;; Vi operator as prefix argument."
  1056. (defun viper-prefix-arg-com (char value com)
  1057. (let ((cont t)
  1058. cmd-info
  1059. cmd-to-exec-at-end)
  1060. (while (and cont
  1061. (viper-memq-char char
  1062. (list ?c ?d ?y ?! ?< ?> ?= ?# ?r ?R ?\"
  1063. viper-buffer-search-char)))
  1064. (if com
  1065. ;; this means that we already have a command character, so we
  1066. ;; construct a com list and exit while. however, if char is "
  1067. ;; it is an error.
  1068. (progn
  1069. ;; new com is (CHAR . OLDCOM)
  1070. (if (viper-memq-char char '(?# ?\")) (error "Viper bell"))
  1071. (setq com (cons char com))
  1072. (setq cont nil))
  1073. ;; If com is nil we set com as char, and read more. Again, if char is
  1074. ;; ", we read the name of register and store it in viper-use-register.
  1075. ;; if char is !, =, or #, a complete com is formed so we exit the while
  1076. ;; loop.
  1077. (cond ((viper-memq-char char '(?! ?=))
  1078. (setq com char)
  1079. (setq char (read-char))
  1080. (setq cont nil))
  1081. ((viper= char ?#)
  1082. ;; read a char and encode it as com
  1083. (setq com (+ 128 (read-char)))
  1084. (setq char (read-char)))
  1085. ((viper= char ?\")
  1086. (let ((reg (read-char)))
  1087. (if (viper-valid-register reg)
  1088. (setq viper-use-register reg)
  1089. (error "Viper bell"))
  1090. (setq char (read-char))))
  1091. (t
  1092. (setq com char)
  1093. (setq char (read-char))))))
  1094. (if (atom com)
  1095. ;; `com' is a single char, so we construct the command argument
  1096. ;; and if `char' is `?', we describe the arg; otherwise
  1097. ;; we prepare the command that will be executed at the end.
  1098. (progn
  1099. (setq cmd-info (cons value com))
  1100. (while (viper= char ?U)
  1101. (viper-describe-arg cmd-info)
  1102. (setq char (read-char)))
  1103. ;; `char' is a movement cmd, a digit arg cmd, or a register cmd---so
  1104. ;; we execute it at the very end
  1105. (or (viper-movement-command-p char)
  1106. (viper-digit-command-p char)
  1107. (viper-regsuffix-command-p char)
  1108. (viper= char ?!) ; bang command
  1109. (viper= char ?g) ; the gg command (like G0)
  1110. (error "Viper bell"))
  1111. (setq cmd-to-exec-at-end
  1112. (viper-exec-form-in-vi
  1113. `(key-binding (char-to-string ,char)))))
  1114. ;; as com is non-nil, this means that we have a command to execute
  1115. (if (viper-memq-char (car com) '(?r ?R))
  1116. ;; execute appropriate region command.
  1117. (let ((char (car com)) (com (cdr com)))
  1118. (setq prefix-arg (cons value com))
  1119. (if (viper= char ?r)
  1120. (viper-region prefix-arg)
  1121. (viper-Region prefix-arg))
  1122. ;; reset prefix-arg
  1123. (setq prefix-arg nil))
  1124. ;; otherwise, reset prefix arg and call appropriate command
  1125. (setq value (if (null value) 1 value))
  1126. (setq prefix-arg nil)
  1127. (cond
  1128. ;; If we change ?C to ?c here, then cc will enter replacement mode
  1129. ;; rather than deleting lines. However, it will affect 1 less line
  1130. ;; than normal. We decided to not use replacement mode here and
  1131. ;; follow Vi, since replacement mode on n full lines can be achieved
  1132. ;; with nC.
  1133. ((equal com '(?c . ?c)) (viper-line (cons value ?C)))
  1134. ((equal com '(?d . ?d)) (viper-line (cons value ?D)))
  1135. ((equal com '(?d . ?y)) (viper-yank-defun))
  1136. ((equal com '(?y . ?y)) (viper-line (cons value ?Y)))
  1137. ((equal com '(?< . ?<)) (viper-line (cons value ?<)))
  1138. ((equal com '(?> . ?>)) (viper-line (cons value ?>)))
  1139. ((equal com '(?! . ?!)) (viper-line (cons value ?!)))
  1140. ((equal com '(?= . ?=)) (viper-line (cons value ?=)))
  1141. ;; gg acts as G0
  1142. ((equal (car com) ?g) (viper-goto-line 0))
  1143. (t (error "Viper bell")))))
  1144. (if cmd-to-exec-at-end
  1145. (progn
  1146. (setq last-command-event
  1147. (viper-copy-event
  1148. (if (featurep 'xemacs) (character-to-event char) char)))
  1149. (condition-case err
  1150. (funcall cmd-to-exec-at-end cmd-info)
  1151. (error
  1152. (error "%s" (error-message-string err))))))
  1153. ))
  1154. (defun viper-describe-arg (arg)
  1155. (let (val com)
  1156. (setq val (viper-P-val arg)
  1157. com (viper-getcom arg))
  1158. (if (null val)
  1159. (if (null com)
  1160. (message "Value is nil, and command is nil")
  1161. (message "Value is nil, and command is `%c'" com))
  1162. (if (null com)
  1163. (message "Value is `%d', and command is nil" val)
  1164. (message "Value is `%d', and command is `%c'" val com)))))
  1165. (defun viper-digit-argument (arg)
  1166. "Begin numeric argument for the next command."
  1167. (interactive "P")
  1168. (viper-leave-region-active)
  1169. (viper-prefix-arg-value
  1170. (viper-last-command-char) (if (consp arg) (cdr arg) nil)))
  1171. (defun viper-command-argument (arg)
  1172. "Accept a motion command as an argument."
  1173. (interactive "P")
  1174. (let ((viper-intermediate-command 'viper-command-argument))
  1175. (condition-case nil
  1176. (viper-prefix-arg-com
  1177. (viper-last-command-char)
  1178. (cond ((null arg) nil)
  1179. ((consp arg) (car arg))
  1180. ((integerp arg) arg)
  1181. (t (error viper-InvalidCommandArgument)))
  1182. (cond ((null arg) nil)
  1183. ((consp arg) (cdr arg))
  1184. ((integerp arg) nil)
  1185. (t (error viper-InvalidCommandArgument))))
  1186. (quit (setq viper-use-register nil)
  1187. (signal 'quit nil)))
  1188. (viper-deactivate-mark)))
  1189. ;; repeat last destructive command
  1190. ;; Append region to text in register REG.
  1191. ;; START and END are buffer positions indicating what to append.
  1192. (defsubst viper-append-to-register (reg start end)
  1193. (set-register reg (concat (if (stringp (get-register reg))
  1194. (get-register reg) "")
  1195. (buffer-substring start end))))
  1196. ;; Saves last inserted text for possible use by viper-repeat command.
  1197. (defun viper-save-last-insertion (beg end)
  1198. (condition-case nil
  1199. (setq viper-last-insertion (buffer-substring beg end))
  1200. (error
  1201. ;; beg or end marker are somehow screwed up
  1202. (setq viper-last-insertion nil)))
  1203. (setq viper-last-insertion (buffer-substring beg end))
  1204. (or (< (length viper-d-com) 5)
  1205. (setcar (nthcdr 4 viper-d-com) viper-last-insertion))
  1206. (or (null viper-command-ring)
  1207. (ring-empty-p viper-command-ring)
  1208. (progn
  1209. (setcar (nthcdr 4 (viper-current-ring-item viper-command-ring))
  1210. viper-last-insertion)
  1211. ;; del most recent elt, if identical to the second most-recent
  1212. (viper-cleanup-ring viper-command-ring)))
  1213. )
  1214. (defsubst viper-yank-last-insertion ()
  1215. "Inserts the text saved by the previous viper-save-last-insertion command."
  1216. (condition-case nil
  1217. (insert viper-last-insertion)
  1218. (error nil)))
  1219. ;; define functions to be executed
  1220. ;; invoked by the `C' command
  1221. (defun viper-exec-change (m-com com)
  1222. (or (and (markerp viper-com-point) (marker-position viper-com-point))
  1223. (set-marker viper-com-point (point) (current-buffer)))
  1224. ;; handle C cmd at the eol and at eob.
  1225. (if (or (and (eolp) (= viper-com-point (point)))
  1226. (= viper-com-point (point-max)))
  1227. (progn
  1228. (insert " ")(backward-char 1)))
  1229. (if (= viper-com-point (point))
  1230. (viper-forward-char-carefully))
  1231. (push-mark viper-com-point)
  1232. (if (eq m-com 'viper-next-line-at-bol)
  1233. (viper-enlarge-region (mark t) (point)))
  1234. (if (< (point) (mark t))
  1235. (exchange-point-and-mark))
  1236. (if (eq (preceding-char) ?\n)
  1237. (viper-backward-char-carefully)) ; give back the newline
  1238. (if (eq viper-intermediate-command 'viper-repeat)
  1239. (viper-change-subr (mark t) (point))
  1240. (viper-change (mark t) (point))))
  1241. ;; this is invoked by viper-substitute-line
  1242. (defun viper-exec-Change (m-com com)
  1243. (save-excursion
  1244. (set-mark viper-com-point)
  1245. (viper-enlarge-region (mark t) (point))
  1246. (if viper-use-register
  1247. (progn
  1248. (cond ((viper-valid-register viper-use-register '(letter digit))
  1249. (copy-to-register
  1250. viper-use-register (mark t) (point) nil))
  1251. ((viper-valid-register viper-use-register '(Letter))
  1252. (viper-append-to-register
  1253. (downcase viper-use-register) (mark t) (point)))
  1254. (t (setq viper-use-register nil)
  1255. (error viper-InvalidRegister viper-use-register)))
  1256. (setq viper-use-register nil)))
  1257. (delete-region (mark t) (point)))
  1258. (open-line 1)
  1259. (if (eq viper-intermediate-command 'viper-repeat)
  1260. (viper-yank-last-insertion)
  1261. (viper-change-state-to-insert)
  1262. ))
  1263. (defun viper-exec-delete (m-com com)
  1264. (or (and (markerp viper-com-point) (marker-position viper-com-point))
  1265. (set-marker viper-com-point (point) (current-buffer)))
  1266. (let (chars-deleted)
  1267. (if viper-use-register
  1268. (progn
  1269. (cond ((viper-valid-register viper-use-register '(letter digit))
  1270. (copy-to-register
  1271. viper-use-register viper-com-point (point) nil))
  1272. ((viper-valid-register viper-use-register '(Letter))
  1273. (viper-append-to-register
  1274. (downcase viper-use-register) viper-com-point (point)))
  1275. (t (setq viper-use-register nil)
  1276. (error viper-InvalidRegister viper-use-register)))
  1277. (setq viper-use-register nil)))
  1278. (setq last-command
  1279. (if (eq last-command 'd-command) 'kill-region nil))
  1280. (setq chars-deleted (abs (- (point) viper-com-point)))
  1281. (if (> chars-deleted viper-change-notification-threshold)
  1282. (unless (viper-is-in-minibuffer)
  1283. (message "Deleted %d characters" chars-deleted)))
  1284. (kill-region viper-com-point (point))
  1285. (setq this-command 'd-command)
  1286. (if viper-ex-style-motion
  1287. (if (and (eolp) (not (bolp))) (backward-char 1)))))
  1288. (defun viper-exec-Delete (m-com com)
  1289. (save-excursion
  1290. (set-mark viper-com-point)
  1291. (viper-enlarge-region (mark t) (point))
  1292. (let (lines-deleted)
  1293. (if viper-use-register
  1294. (progn
  1295. (cond ((viper-valid-register viper-use-register '(letter digit))
  1296. (copy-to-register
  1297. viper-use-register (mark t) (point) nil))
  1298. ((viper-valid-register viper-use-register '(Letter))
  1299. (viper-append-to-register
  1300. (downcase viper-use-register) (mark t) (point)))
  1301. (t (setq viper-use-register nil)
  1302. (error viper-InvalidRegister viper-use-register)))
  1303. (setq viper-use-register nil)))
  1304. (setq last-command
  1305. (if (eq last-command 'D-command) 'kill-region nil))
  1306. (setq lines-deleted (count-lines (point) viper-com-point))
  1307. (if (> lines-deleted viper-change-notification-threshold)
  1308. (unless (viper-is-in-minibuffer)
  1309. (message "Deleted %d lines" lines-deleted)))
  1310. (kill-region (mark t) (point))
  1311. (if (eq m-com 'viper-line) (setq this-command 'D-command)))
  1312. (back-to-indentation)))
  1313. ;; save region
  1314. (defun viper-exec-yank (m-com com)
  1315. (or (and (markerp viper-com-point) (marker-position viper-com-point))
  1316. (set-marker viper-com-point (point) (current-buffer)))
  1317. (let (chars-saved)
  1318. (if viper-use-register
  1319. (progn
  1320. (cond ((viper-valid-register viper-use-register '(letter digit))
  1321. (copy-to-register
  1322. viper-use-register viper-com-point (point) nil))
  1323. ((viper-valid-register viper-use-register '(Letter))
  1324. (viper-append-to-register
  1325. (downcase viper-use-register) viper-com-point (point)))
  1326. (t (setq viper-use-register nil)
  1327. (error viper-InvalidRegister viper-use-register)))
  1328. (setq viper-use-register nil)))
  1329. (setq last-command nil)
  1330. (copy-region-as-kill viper-com-point (point))
  1331. (setq chars-saved (abs (- (point) viper-com-point)))
  1332. (if (> chars-saved viper-change-notification-threshold)
  1333. (unless (viper-is-in-minibuffer)
  1334. (message "Saved %d characters" chars-saved)))
  1335. (goto-char viper-com-point)))
  1336. ;; save lines
  1337. (defun viper-exec-Yank (m-com com)
  1338. (save-excursion
  1339. (set-mark viper-com-point)
  1340. (viper-enlarge-region (mark t) (point))
  1341. (let (lines-saved)
  1342. (if viper-use-register
  1343. (progn
  1344. (cond ((viper-valid-register viper-use-register '(letter digit))
  1345. (copy-to-register
  1346. viper-use-register (mark t) (point) nil))
  1347. ((viper-valid-register viper-use-register '(Letter))
  1348. (viper-append-to-register
  1349. (downcase viper-use-register) (mark t) (point)))
  1350. (t (setq viper-use-register nil)
  1351. (error viper-InvalidRegister viper-use-register)))
  1352. (setq viper-use-register nil)))
  1353. (setq last-command nil)
  1354. (copy-region-as-kill (mark t) (point))
  1355. (setq lines-saved (count-lines (mark t) (point)))
  1356. (if (> lines-saved viper-change-notification-threshold)
  1357. (unless (viper-is-in-minibuffer)
  1358. (message "Saved %d lines" lines-saved)))))
  1359. (viper-deactivate-mark)
  1360. (goto-char viper-com-point))
  1361. (defun viper-exec-bang (m-com com)
  1362. (save-excursion
  1363. (set-mark viper-com-point)
  1364. (viper-enlarge-region (mark t) (point))
  1365. (exchange-point-and-mark)
  1366. (shell-command-on-region
  1367. (mark t) (point)
  1368. (if (viper= com ?!)
  1369. (setq viper-last-shell-com
  1370. (viper-read-string-with-history
  1371. "!"
  1372. nil
  1373. 'viper-shell-history
  1374. (car viper-shell-history)
  1375. ))
  1376. viper-last-shell-com)
  1377. t)))
  1378. (defun viper-exec-equals (m-com com)
  1379. (save-excursion
  1380. (set-mark viper-com-point)
  1381. (viper-enlarge-region (mark t) (point))
  1382. (if (> (mark t) (point)) (exchange-point-and-mark))
  1383. (indent-region (mark t) (point) nil)))
  1384. (defun viper-exec-shift (m-com com)
  1385. (save-excursion
  1386. (set-mark viper-com-point)
  1387. (viper-enlarge-region (mark t) (point))
  1388. (if (> (mark t) (point)) (exchange-point-and-mark))
  1389. (indent-rigidly (mark t) (point)
  1390. (if (viper= com ?>)
  1391. viper-shift-width
  1392. (- viper-shift-width))))
  1393. ;; return point to where it was before shift
  1394. (goto-char viper-com-point))
  1395. ;; this is needed because some commands fake com by setting it to ?r, which
  1396. ;; denotes repeated insert command.
  1397. (defsubst viper-exec-dummy (m-com com)
  1398. nil)
  1399. (defun viper-exec-buffer-search (m-com com)
  1400. (setq viper-s-string
  1401. (regexp-quote (buffer-substring (point) viper-com-point)))
  1402. (setq viper-s-forward t)
  1403. (setq viper-search-history (cons viper-s-string viper-search-history))
  1404. (setq viper-intermediate-command 'viper-exec-buffer-search)
  1405. (viper-search viper-s-string viper-s-forward 1))
  1406. (defvar viper-exec-array (make-vector 128 nil))
  1407. ;; Using a dispatch array allows adding functions like buffer search
  1408. ;; without affecting other functions. Buffer search can now be bound
  1409. ;; to any character.
  1410. (aset viper-exec-array ?c 'viper-exec-change)
  1411. (aset viper-exec-array ?C 'viper-exec-Change)
  1412. (aset viper-exec-array ?d 'viper-exec-delete)
  1413. (aset viper-exec-array ?D 'viper-exec-Delete)
  1414. (aset viper-exec-array ?y 'viper-exec-yank)
  1415. (aset viper-exec-array ?Y 'viper-exec-Yank)
  1416. (aset viper-exec-array ?r 'viper-exec-dummy)
  1417. (aset viper-exec-array ?! 'viper-exec-bang)
  1418. (aset viper-exec-array ?< 'viper-exec-shift)
  1419. (aset viper-exec-array ?> 'viper-exec-shift)
  1420. (aset viper-exec-array ?= 'viper-exec-equals)
  1421. ;; This function is called by various movement commands to execute a
  1422. ;; destructive command on the region specified by the movement command. For
  1423. ;; instance, if the user types cw, then the command viper-forward-word will
  1424. ;; call viper-execute-com to execute viper-exec-change, which eventually will
  1425. ;; call viper-change to invoke the replace mode on the region.
  1426. ;;
  1427. ;; The var viper-d-com is set to (M-COM VAL COM REG INSERTED-TEXT COMMAND-KEYS)
  1428. ;; via a call to viper-set-destructive-command, for later use by viper-repeat.
  1429. (defun viper-execute-com (m-com val com)
  1430. (let ((reg viper-use-register))
  1431. ;; this is the special command `#'
  1432. (if (> com 128)
  1433. (viper-special-prefix-com (- com 128))
  1434. (let ((fn (aref viper-exec-array com)))
  1435. (if (null fn)
  1436. (error "%c: %s" com viper-InvalidViCommand)
  1437. (funcall fn m-com com))))
  1438. (if (viper-dotable-command-p com)
  1439. (viper-set-destructive-command
  1440. (list m-com val com reg nil nil)))
  1441. ))
  1442. (defun viper-repeat (arg)
  1443. "Re-execute last destructive command.
  1444. Use the info in viper-d-com, which has the form
  1445. \(com val ch reg inserted-text command-keys\),
  1446. where `com' is the command to be re-executed, `val' is the
  1447. argument to `com', `ch' is a flag for repeat, and `reg' is optional;
  1448. if it exists, it is the name of the register for `com'.
  1449. If the prefix argument ARG is non-nil, it is used instead of `val'."
  1450. (interactive "P")
  1451. (let ((save-point (point)) ; save point before repeating prev cmd
  1452. ;; Pass along that we are repeating a destructive command
  1453. ;; This tells viper-set-destructive-command not to update
  1454. ;; viper-command-ring
  1455. (viper-intermediate-command 'viper-repeat))
  1456. (if (eq last-command 'viper-undo)
  1457. ;; if the last command was viper-undo, then undo-more
  1458. (viper-undo-more)
  1459. ;; otherwise execute the command stored in viper-d-com. if arg is
  1460. ;; non-nil its prefix value is used as new prefix value for the command.
  1461. (let ((m-com (car viper-d-com))
  1462. (val (viper-P-val arg))
  1463. (com (nth 2 viper-d-com))
  1464. (reg (nth 3 viper-d-com)))
  1465. (if (null val) (setq val (nth 1 viper-d-com)))
  1466. (if (null m-com) (error "No previous command to repeat"))
  1467. (setq viper-use-register reg)
  1468. (if (nth 4 viper-d-com) ; text inserted by command
  1469. (setq viper-last-insertion (nth 4 viper-d-com)
  1470. viper-d-char (nth 4 viper-d-com)))
  1471. (funcall m-com (cons val com))
  1472. (cond ((and (< save-point (point)) viper-keep-point-on-repeat)
  1473. (goto-char save-point)) ; go back to before repeat.
  1474. ((and (< save-point (point)) viper-ex-style-editing)
  1475. (or (bolp) (backward-char 1))))
  1476. (if (and (eolp) (not (bolp)))
  1477. (backward-char 1))
  1478. ))
  1479. (viper-adjust-undo) ; take care of undo
  1480. ;; If the prev cmd was rotating the command ring, this means that `.' has
  1481. ;; just executed a command from that ring. So, push it on the ring again.
  1482. ;; If we are just executing previous command , then don't push viper-d-com
  1483. ;; because viper-d-com is not fully constructed in this case (its keys and
  1484. ;; the inserted text may be nil). Besides, in this case, the command
  1485. ;; executed by `.' is already on the ring.
  1486. (if (eq last-command 'viper-display-current-destructive-command)
  1487. (viper-push-onto-ring viper-d-com 'viper-command-ring))
  1488. (viper-deactivate-mark)
  1489. ))
  1490. (defun viper-repeat-from-history ()
  1491. "Repeat a destructive command from history.
  1492. Doesn't change viper-command-ring in any way, so `.' will work as before
  1493. executing this command.
  1494. This command is supposed to be bound to a two-character Vi macro where
  1495. the second character is a digit 0 to 9. The digit indicates which
  1496. history command to execute. `<char>0' is equivalent to `.', `<char>1'
  1497. invokes the command before that, etc."
  1498. (interactive)
  1499. (let* ((viper-intermediate-command 'repeating-display-destructive-command)
  1500. (idx (cond (viper-this-kbd-macro
  1501. (string-to-number
  1502. (symbol-name (elt viper-this-kbd-macro 1))))
  1503. (t 0)))
  1504. (num idx)
  1505. (viper-d-com viper-d-com))
  1506. (or (and (numberp num) (<= 0 num) (<= num 9))
  1507. (progn
  1508. (setq idx 0
  1509. num 0)
  1510. (message
  1511. "`viper-repeat-from-history' must be invoked as a Vi macro bound to `<key><digit>'")))
  1512. (while (< 0 num)
  1513. (setq viper-d-com (viper-special-ring-rotate1 viper-command-ring -1))
  1514. (setq num (1- num)))
  1515. (viper-repeat nil)
  1516. (while (> idx num)
  1517. (viper-special-ring-rotate1 viper-command-ring 1)
  1518. (setq num (1+ num)))
  1519. ))
  1520. ;; The hash-command. It is invoked interactively by the key sequence #<char>.
  1521. ;; The chars that can follow `#' are determined by viper-hash-command-p
  1522. (defun viper-special-prefix-com (char)
  1523. (cond ((viper= char ?c)
  1524. (downcase-region (min viper-com-point (point))
  1525. (max viper-com-point (point))))
  1526. ((viper= char ?C)
  1527. (upcase-region (min viper-com-point (point))
  1528. (max viper-com-point (point))))
  1529. ((viper= char ?g)
  1530. (push-mark viper-com-point t)
  1531. ;; execute the last emacs kbd macro on each line of the region
  1532. (viper-global-execute))
  1533. ((viper= char ?q)
  1534. (push-mark viper-com-point t)
  1535. (viper-quote-region))
  1536. ((viper= char ?s)
  1537. (funcall viper-spell-function viper-com-point (point)))
  1538. (t (error "#%c: %s" char viper-InvalidViCommand))))
  1539. ;; undoing
  1540. ;; hook used inside undo
  1541. (defvar viper-undo-functions nil)
  1542. ;; Runs viper-before-change-functions inside before-change-functions
  1543. (defun viper-undo-sentinel (beg end length)
  1544. (run-hook-with-args 'viper-undo-functions beg end length))
  1545. (add-hook 'after-change-functions 'viper-undo-sentinel)
  1546. ;; Hook used in viper-undo
  1547. (defun viper-after-change-undo-hook (beg end len)
  1548. (if (and (boundp 'undo-in-progress) undo-in-progress)
  1549. (setq undo-beg-posn beg
  1550. undo-end-posn (or end beg))
  1551. ;; some other hooks may be changing various text properties in
  1552. ;; the buffer in response to 'undo'; so remove this hook to avoid
  1553. ;; its repeated invocation
  1554. (remove-hook 'viper-undo-functions 'viper-after-change-undo-hook 'local)
  1555. ))
  1556. (defun viper-undo ()
  1557. "Undo previous change."
  1558. (interactive)
  1559. (message "undo!")
  1560. (let ((modified (buffer-modified-p))
  1561. (before-undo-pt (point-marker))
  1562. undo-beg-posn undo-end-posn)
  1563. ;; the viper-after-change-undo-hook removes itself after the 1st invocation
  1564. (add-hook 'viper-undo-functions 'viper-after-change-undo-hook nil 'local)
  1565. (undo-start)
  1566. (undo-more 2)
  1567. ;;(setq undo-beg-posn (or undo-beg-posn (point))
  1568. ;; undo-end-posn (or undo-end-posn (point)))
  1569. ;;(setq undo-beg-posn (or undo-beg-posn before-undo-pt)
  1570. ;; undo-end-posn (or undo-end-posn undo-beg-posn))
  1571. (if (and undo-beg-posn undo-end-posn)
  1572. (progn
  1573. (goto-char undo-beg-posn)
  1574. (sit-for 0)
  1575. (if (and viper-keep-point-on-undo
  1576. (pos-visible-in-window-p before-undo-pt))
  1577. (progn
  1578. (push-mark (point-marker) t)
  1579. (viper-sit-for-short 300)
  1580. (goto-char undo-end-posn)
  1581. (viper-sit-for-short 300)
  1582. (if (pos-visible-in-window-p undo-beg-posn)
  1583. (goto-char before-undo-pt)
  1584. (goto-char undo-beg-posn)))
  1585. (push-mark before-undo-pt t))
  1586. ))
  1587. (if (and (eolp) (not (bolp))) (backward-char 1))
  1588. )
  1589. (setq this-command 'viper-undo))
  1590. ;; Continue undoing previous changes.
  1591. (defun viper-undo-more ()
  1592. (message "undo more!")
  1593. (condition-case nil
  1594. (undo-more 1)
  1595. (error (beep)
  1596. (message "No further undo information in this buffer")))
  1597. (if (and (eolp) (not (bolp))) (backward-char 1))
  1598. (setq this-command 'viper-undo))
  1599. ;; The following two functions are used to set up undo properly.
  1600. ;; In VI, unlike Emacs, if you open a line, say, and add a bunch of lines,
  1601. ;; they are undone all at once.
  1602. (defun viper-adjust-undo ()
  1603. (if viper-undo-needs-adjustment
  1604. (let ((inhibit-quit t)
  1605. tmp tmp2)
  1606. (setq viper-undo-needs-adjustment nil)
  1607. (if (listp buffer-undo-list)
  1608. (if (setq tmp (memq viper-buffer-undo-list-mark buffer-undo-list))
  1609. (progn
  1610. (setq tmp2 (cdr tmp)) ; the part after mark
  1611. ;; cut tail from buffer-undo-list temporarily by direct
  1612. ;; manipulation with pointers in buffer-undo-list
  1613. (setcdr tmp nil)
  1614. (setq buffer-undo-list (delq nil buffer-undo-list))
  1615. (setq buffer-undo-list
  1616. (delq viper-buffer-undo-list-mark buffer-undo-list))
  1617. ;; restore tail of buffer-undo-list
  1618. (setq buffer-undo-list (nconc buffer-undo-list tmp2)))
  1619. (setq buffer-undo-list (delq nil buffer-undo-list)))))
  1620. ))
  1621. (defun viper-set-complex-command-for-undo ()
  1622. (if (listp buffer-undo-list)
  1623. (if (not viper-undo-needs-adjustment)
  1624. (let ((inhibit-quit t))
  1625. (setq buffer-undo-list
  1626. (cons viper-buffer-undo-list-mark buffer-undo-list))
  1627. (setq viper-undo-needs-adjustment t)))))
  1628. ;;; Viper's destructive Command ring utilities
  1629. (defun viper-display-current-destructive-command ()
  1630. (let ((text (nth 4 viper-d-com))
  1631. (keys (nth 5 viper-d-com))
  1632. (max-text-len 30))
  1633. (setq this-command 'viper-display-current-destructive-command)
  1634. (message " `.' runs %s%s"
  1635. (concat "`" (viper-array-to-string keys) "'")
  1636. (viper-abbreviate-string
  1637. (if (featurep 'xemacs)
  1638. (replace-in-string ; xemacs
  1639. (cond ((characterp text) (char-to-string text))
  1640. ((stringp text) text)
  1641. (t ""))
  1642. "\n" "^J")
  1643. text ; emacs
  1644. )
  1645. max-text-len
  1646. " inserting `" "'" " ......."))
  1647. ))
  1648. ;; don't change viper-d-com if it was viper-repeat command invoked with `.'
  1649. ;; or in some other way (non-interactively).
  1650. (defun viper-set-destructive-command (list)
  1651. (or (eq viper-intermediate-command 'viper-repeat)
  1652. (progn
  1653. (setq viper-d-com list)
  1654. (setcar (nthcdr 5 viper-d-com)
  1655. (viper-array-to-string (if (arrayp viper-this-command-keys)
  1656. viper-this-command-keys
  1657. (this-command-keys))))
  1658. (viper-push-onto-ring viper-d-com 'viper-command-ring)))
  1659. (setq viper-this-command-keys nil))
  1660. (defun viper-prev-destructive-command (next)
  1661. "Find previous destructive command in the history of destructive commands.
  1662. With prefix argument, find next destructive command."
  1663. (interactive "P")
  1664. (let (cmd viper-intermediate-command)
  1665. (if (eq last-command 'viper-display-current-destructive-command)
  1666. ;; repeated search through command history
  1667. (setq viper-intermediate-command
  1668. 'repeating-display-destructive-command)
  1669. ;; first search through command history--set temp ring
  1670. (setq viper-temp-command-ring (ring-copy viper-command-ring)))
  1671. (setq cmd (if next
  1672. (viper-special-ring-rotate1 viper-temp-command-ring 1)
  1673. (viper-special-ring-rotate1 viper-temp-command-ring -1)))
  1674. (if (null cmd)
  1675. ()
  1676. (setq viper-d-com cmd))
  1677. (viper-display-current-destructive-command)))
  1678. (defun viper-next-destructive-command ()
  1679. "Find next destructive command in the history of destructive commands."
  1680. (interactive)
  1681. (viper-prev-destructive-command 'next))
  1682. (defun viper-insert-prev-from-insertion-ring (arg)
  1683. "Cycle through insertion ring in the direction of older insertions.
  1684. Undoes previous insertion and inserts new.
  1685. With prefix argument, cycles in the direction of newer elements.
  1686. In minibuffer, this command executes whatever the invocation key is bound
  1687. to in the global map, instead of cycling through the insertion ring."
  1688. (interactive "P")
  1689. (let (viper-intermediate-command)
  1690. (if (eq last-command 'viper-insert-from-insertion-ring)
  1691. (progn ; repeated search through insertion history
  1692. (setq viper-intermediate-command 'repeating-insertion-from-ring)
  1693. (if (eq viper-current-state 'replace-state)
  1694. (undo 1)
  1695. (if viper-last-inserted-string-from-insertion-ring
  1696. (backward-delete-char
  1697. (length viper-last-inserted-string-from-insertion-ring))))
  1698. )
  1699. ;;first search through insertion history
  1700. (setq viper-temp-insertion-ring (ring-copy viper-insertion-ring)))
  1701. (setq this-command 'viper-insert-from-insertion-ring)
  1702. ;; so that things will be undone properly
  1703. (setq buffer-undo-list (cons nil buffer-undo-list))
  1704. (setq viper-last-inserted-string-from-insertion-ring
  1705. (viper-special-ring-rotate1 viper-temp-insertion-ring (if arg 1 -1)))
  1706. ;; this change of viper-intermediate-command must come after
  1707. ;; viper-special-ring-rotate1, so that the ring will rotate, but before the
  1708. ;; insertion.
  1709. (setq viper-intermediate-command nil)
  1710. (if viper-last-inserted-string-from-insertion-ring
  1711. (insert viper-last-inserted-string-from-insertion-ring))
  1712. ))
  1713. (defun viper-insert-next-from-insertion-ring ()
  1714. "Cycle through insertion ring in the direction of older insertions.
  1715. Undo previous insertion and inserts new."
  1716. (interactive)
  1717. (viper-insert-prev-from-insertion-ring 'next))
  1718. ;; some region utilities
  1719. ;; If at the last line of buffer, add \\n before eob, if newline is missing.
  1720. (defun viper-add-newline-at-eob-if-necessary ()
  1721. (save-excursion
  1722. (end-of-line)
  1723. ;; make sure all lines end with newline, unless in the minibuffer or
  1724. ;; when requested otherwise (require-final-newline is nil)
  1725. (save-restriction
  1726. (widen)
  1727. (if (and (eobp)
  1728. (not (bolp))
  1729. require-final-newline
  1730. ;; add newline only if we actually edited buffer. otherwise it
  1731. ;; might unintentionally modify binary buffers
  1732. (buffer-modified-p)
  1733. (not (viper-is-in-minibuffer))
  1734. (not buffer-read-only))
  1735. ;; text property may be read-only
  1736. (condition-case nil
  1737. (insert "\n")
  1738. (error nil))
  1739. ))
  1740. ))
  1741. (defun viper-yank-defun ()
  1742. (mark-defun)
  1743. (copy-region-as-kill (point) (mark t)))
  1744. ;; Enlarge region between BEG and END.
  1745. (defun viper-enlarge-region (beg end)
  1746. (or beg (setq beg end)) ; if beg is nil, set to end
  1747. (or end (setq end beg)) ; if end is nil, set to beg
  1748. (if (< beg end)
  1749. (progn (goto-char beg) (set-mark end))
  1750. (goto-char end)
  1751. (set-mark beg))
  1752. (beginning-of-line)
  1753. (exchange-point-and-mark)
  1754. (if (or (not (eobp)) (not (bolp))) (forward-line 1))
  1755. (if (not (eobp)) (beginning-of-line))
  1756. (if (> beg end) (exchange-point-and-mark)))
  1757. ;; Quote region by each line with a user supplied string.
  1758. (defun viper-quote-region ()
  1759. (let ((quote-str viper-quote-string)
  1760. (donot-change-default t))
  1761. (setq quote-str
  1762. (viper-read-string-with-history
  1763. "Quote string: "
  1764. nil
  1765. 'viper-quote-region-history
  1766. (cond ((string-match "tex.*-mode" (symbol-name major-mode)) "%%")
  1767. ((string-match "java.*-mode" (symbol-name major-mode)) "//")
  1768. ((string-match "perl.*-mode" (symbol-name major-mode)) "#")
  1769. ((string-match "lisp.*-mode" (symbol-name major-mode)) ";;")
  1770. ((memq major-mode '(c-mode cc-mode c++-mode)) "//")
  1771. ((memq major-mode '(sh-mode shell-mode)) "#")
  1772. (t (setq donot-change-default nil)
  1773. quote-str))))
  1774. (or donot-change-default
  1775. (setq viper-quote-string quote-str))
  1776. (viper-enlarge-region (point) (mark t))
  1777. (if (> (point) (mark t)) (exchange-point-and-mark))
  1778. (insert quote-str)
  1779. (beginning-of-line)
  1780. (forward-line 1)
  1781. (while (and (< (point) (mark t)) (bolp))
  1782. (insert quote-str)
  1783. (beginning-of-line)
  1784. (forward-line 1))))
  1785. ;; Tells whether BEG is on the same line as END.
  1786. ;; If one of the args is nil, it'll return nil.
  1787. (defun viper-same-line (beg end)
  1788. (let ((selective-display nil)
  1789. (incr 0)
  1790. temp)
  1791. (if (and beg end (> beg end))
  1792. (setq temp beg
  1793. beg end
  1794. end temp))
  1795. (if (and beg end)
  1796. (cond ((or (> beg (point-max)) (> end (point-max))) ; out of range
  1797. nil)
  1798. (t
  1799. ;; This 'if' is needed because Emacs treats the next empty line
  1800. ;; as part of the previous line.
  1801. (if (= (viper-line-pos 'start) end)
  1802. (setq incr 1))
  1803. (<= (+ incr (count-lines beg end)) 1))))
  1804. ))
  1805. ;; Check if the string ends with a newline.
  1806. (defun viper-end-with-a-newline-p (string)
  1807. (or (string= string "")
  1808. (= (viper-seq-last-elt string) ?\n)))
  1809. (defun viper-tmp-insert-at-eob (msg)
  1810. (let ((savemax (point-max)))
  1811. (goto-char savemax)
  1812. (insert msg)
  1813. (sit-for 2)
  1814. (goto-char savemax) (delete-region (point) (point-max))
  1815. ))
  1816. ;;; Minibuffer business
  1817. (defsubst viper-set-minibuffer-style ()
  1818. (add-hook 'minibuffer-setup-hook 'viper-minibuffer-setup-sentinel)
  1819. (add-hook 'post-command-hook 'viper-minibuffer-post-command-hook))
  1820. (defun viper-minibuffer-setup-sentinel ()
  1821. (let ((hook (if viper-vi-style-in-minibuffer
  1822. 'viper-change-state-to-insert
  1823. 'viper-change-state-to-emacs)))
  1824. ;; making buffer-local variables so that normal buffers won't affect the
  1825. ;; minibuffer and vice versa. Otherwise, command arguments will affect
  1826. ;; minibuffer ops and insertions from the minibuffer will change those in
  1827. ;; the normal buffers
  1828. (make-local-variable 'viper-d-com)
  1829. (make-local-variable 'viper-last-insertion)
  1830. (make-local-variable 'viper-command-ring)
  1831. (setq viper-d-com nil
  1832. viper-last-insertion nil
  1833. viper-command-ring nil)
  1834. (funcall hook)
  1835. ))
  1836. ;; This is a temp hook that uses free variables init-message and viper-initial.
  1837. ;; A dirty feature, but it is the simplest way to have it do the right thing.
  1838. ;; The INIT-MESSAGE and VIPER-INITIAL vars come from the scope set by
  1839. ;; viper-read-string-with-history
  1840. (defun viper-minibuffer-standard-hook ()
  1841. (if (stringp init-message)
  1842. (viper-tmp-insert-at-eob init-message))
  1843. (when (stringp viper-initial)
  1844. ;; don't wait if we have unread events or in kbd macro
  1845. (or unread-command-events
  1846. executing-kbd-macro
  1847. (sit-for 840))
  1848. (if (fboundp 'minibuffer-prompt-end)
  1849. (delete-region (minibuffer-prompt-end) (point-max))
  1850. (erase-buffer))
  1851. (insert viper-initial)))
  1852. (defsubst viper-minibuffer-real-start ()
  1853. (if (fboundp 'minibuffer-prompt-end)
  1854. (minibuffer-prompt-end)
  1855. (point-min)))
  1856. (defun viper-minibuffer-post-command-hook()
  1857. (when (active-minibuffer-window)
  1858. (when (< (point) (viper-minibuffer-real-start))
  1859. (goto-char (viper-minibuffer-real-start)))))
  1860. ;; Interpret last event in the local map first; if fails, use exit-minibuffer.
  1861. ;; Run viper-minibuffer-exit-hook before exiting.
  1862. (defun viper-exit-minibuffer ()
  1863. "Exit minibuffer Viper way."
  1864. (interactive)
  1865. (let (command)
  1866. (setq command (local-key-binding (char-to-string (viper-last-command-char))))
  1867. (run-hooks 'viper-minibuffer-exit-hook)
  1868. (if command
  1869. (command-execute command)
  1870. (exit-minibuffer))))
  1871. (defcustom viper-smart-suffix-list
  1872. '("" "tex" "c" "cc" "C" "java" "el" "html" "htm" "xml"
  1873. "pl" "flr" "P" "p" "h" "H")
  1874. "*List of suffixes that Viper tries to append to filenames ending with a `.'.
  1875. This is useful when the current directory contains files with the same
  1876. prefix and many different suffixes. Usually, only one of the suffixes
  1877. represents an editable file. However, file completion will stop at the `.'
  1878. The smart suffix feature lets you hit RET in such a case, and Viper will
  1879. select the appropriate suffix.
  1880. Suffixes are tried in the order given and the first suffix for which a
  1881. corresponding file exists is selected. If no file exists for any of the
  1882. suffixes, the user is asked to confirm.
  1883. To turn this feature off, set this variable to nil."
  1884. :type '(repeat string)
  1885. :group 'viper-misc)
  1886. ;; Try to add a suitable suffix to files whose name ends with a `.'
  1887. ;; Useful when the user hits RET on a non-completed file name.
  1888. ;; Used as a minibuffer exit hook in read-file-name
  1889. (defun viper-file-add-suffix ()
  1890. (let ((count 0)
  1891. (len (length viper-smart-suffix-list))
  1892. (file (buffer-substring-no-properties
  1893. (viper-minibuffer-real-start) (point-max)))
  1894. found key cmd suff)
  1895. (goto-char (point-max))
  1896. (if (and viper-smart-suffix-list (string-match "\\.$" file))
  1897. (progn
  1898. (while (and (not found) (< count len))
  1899. (setq suff (nth count viper-smart-suffix-list)
  1900. count (1+ count))
  1901. (if (file-exists-p
  1902. (format "%s%s" (substitute-in-file-name file) suff))
  1903. (progn
  1904. (setq found t)
  1905. (insert suff))))
  1906. (if found
  1907. ()
  1908. (viper-tmp-insert-at-eob " [Please complete file name]")
  1909. (unwind-protect
  1910. (while (not (memq cmd
  1911. '(exit-minibuffer viper-exit-minibuffer)))
  1912. (setq cmd
  1913. (key-binding (setq key (read-key-sequence nil))))
  1914. (cond ((eq cmd 'self-insert-command)
  1915. (if (featurep 'xemacs)
  1916. (insert (events-to-keys key)) ; xemacs
  1917. (insert key) ; emacs
  1918. ))
  1919. ((memq cmd '(exit-minibuffer viper-exit-minibuffer))
  1920. nil)
  1921. (t (command-execute cmd)))
  1922. )))
  1923. ))))
  1924. (defun viper-minibuffer-trim-tail ()
  1925. "Delete junk at the end of the first line of the minibuffer input.
  1926. Remove this function from `viper-minibuffer-exit-hook', if this causes
  1927. problems."
  1928. (if (viper-is-in-minibuffer)
  1929. (let ((inhibit-field-text-motion t))
  1930. (goto-char (viper-minibuffer-real-start))
  1931. (end-of-line)
  1932. (delete-region (point) (point-max)))))
  1933. ;;; Reading string with history
  1934. (defun viper-read-string-with-history (prompt &optional viper-initial
  1935. history-var default keymap
  1936. init-message)
  1937. ;; Read string, prompting with PROMPT and inserting the VIPER-INITIAL
  1938. ;; value. Uses HISTORY-VAR. DEFAULT is the default value to accept if the
  1939. ;; input is an empty string.
  1940. ;; Default value is displayed until the user types something in the
  1941. ;; minibuffer.
  1942. ;; KEYMAP is used, if given, instead of minibuffer-local-map.
  1943. ;; INIT-MESSAGE is the message temporarily displayed after entering the
  1944. ;; minibuffer.
  1945. (let ((minibuffer-setup-hook
  1946. ;; stolen from add-hook
  1947. (let ((old
  1948. (if (boundp 'minibuffer-setup-hook)
  1949. minibuffer-setup-hook
  1950. nil)))
  1951. (cons
  1952. 'viper-minibuffer-standard-hook
  1953. (if (or (not (listp old)) (eq (car old) 'lambda))
  1954. (list old) old))))
  1955. (val "")
  1956. (padding "")
  1957. temp-msg)
  1958. (setq keymap (or keymap minibuffer-local-map)
  1959. viper-initial (or viper-initial "")
  1960. temp-msg (if default
  1961. (format "(default %s) " default)
  1962. ""))
  1963. (setq viper-incomplete-ex-cmd nil)
  1964. (setq val (read-from-minibuffer prompt
  1965. (concat temp-msg viper-initial val padding)
  1966. keymap nil history-var))
  1967. (setq minibuffer-setup-hook nil
  1968. padding (viper-array-to-string (this-command-keys))
  1969. temp-msg "")
  1970. ;; the following tries to be smart about what to put in history
  1971. (if (not (string= val (car (eval history-var))))
  1972. (set history-var (cons val (eval history-var))))
  1973. (if (or (string= (nth 0 (eval history-var)) (nth 1 (eval history-var)))
  1974. (string= (nth 0 (eval history-var)) ""))
  1975. (set history-var (cdr (eval history-var))))
  1976. ;; If the user enters nothing but the prev cmd wasn't viper-ex,
  1977. ;; viper-command-argument, or `! shell-command', this probably means
  1978. ;; that the user typed something then erased. Return "" in this case, not
  1979. ;; the default---the default is too confusing in this case.
  1980. (cond ((and (string= val "")
  1981. (not (string= prompt "!")) ; was a `! shell-command'
  1982. (not (memq last-command
  1983. '(viper-ex
  1984. viper-command-argument
  1985. t)
  1986. )))
  1987. "")
  1988. ((string= val "") (or default ""))
  1989. (t val))
  1990. ))
  1991. ;; insertion commands
  1992. ;; Called when state changes from Insert Vi command mode.
  1993. ;; Repeats the insertion command if Insert state was entered with prefix
  1994. ;; argument > 1.
  1995. (defun viper-repeat-insert-command ()
  1996. (let ((i-com (car viper-d-com))
  1997. (val (nth 1 viper-d-com))
  1998. (char (nth 2 viper-d-com)))
  1999. (if (and val (> val 1)) ; first check that val is non-nil
  2000. (progn
  2001. (setq viper-d-com (list i-com (1- val) ?r nil nil nil))
  2002. (viper-repeat nil)
  2003. (setq viper-d-com (list i-com val char nil nil nil))
  2004. ))))
  2005. (defun viper-insert (arg)
  2006. "Insert before point."
  2007. (interactive "P")
  2008. (viper-set-complex-command-for-undo)
  2009. (let ((val (viper-p-val arg))
  2010. ;;(com (viper-getcom arg))
  2011. )
  2012. (viper-set-destructive-command (list 'viper-insert val ?r nil nil nil))
  2013. (if (eq viper-intermediate-command 'viper-repeat)
  2014. (viper-loop val (viper-yank-last-insertion))
  2015. (viper-change-state-to-insert))))
  2016. (defun viper-append (arg)
  2017. "Append after point."
  2018. (interactive "P")
  2019. (viper-set-complex-command-for-undo)
  2020. (let ((val (viper-p-val arg))
  2021. ;;(com (viper-getcom arg))
  2022. )
  2023. (viper-set-destructive-command (list 'viper-append val ?r nil nil nil))
  2024. (if (not (eolp)) (forward-char))
  2025. (if (eq viper-intermediate-command 'viper-repeat)
  2026. (viper-loop val (viper-yank-last-insertion))
  2027. (viper-change-state-to-insert))))
  2028. (defun viper-Append (arg)
  2029. "Append at end of line."
  2030. (interactive "P")
  2031. (viper-set-complex-command-for-undo)
  2032. (let ((val (viper-p-val arg))
  2033. ;;(com (viper-getcom arg))
  2034. )
  2035. (viper-set-destructive-command (list 'viper-Append val ?r nil nil nil))
  2036. (end-of-line)
  2037. (if (eq viper-intermediate-command 'viper-repeat)
  2038. (viper-loop val (viper-yank-last-insertion))
  2039. (viper-change-state-to-insert))))
  2040. (defun viper-Insert (arg)
  2041. "Insert before first non-white."
  2042. (interactive "P")
  2043. (viper-set-complex-command-for-undo)
  2044. (let ((val (viper-p-val arg))
  2045. ;;(com (viper-getcom arg))
  2046. )
  2047. (viper-set-destructive-command (list 'viper-Insert val ?r nil nil nil))
  2048. (back-to-indentation)
  2049. (if (eq viper-intermediate-command 'viper-repeat)
  2050. (viper-loop val (viper-yank-last-insertion))
  2051. (viper-change-state-to-insert))))
  2052. (defun viper-open-line (arg)
  2053. "Open line below."
  2054. (interactive "P")
  2055. (viper-set-complex-command-for-undo)
  2056. (let ((val (viper-p-val arg))
  2057. ;;(com (viper-getcom arg))
  2058. )
  2059. (viper-set-destructive-command (list 'viper-open-line val ?r nil nil nil))
  2060. (let ((col (current-indentation)))
  2061. (if (eq viper-intermediate-command 'viper-repeat)
  2062. (viper-loop val
  2063. (end-of-line)
  2064. (newline 1)
  2065. (viper-indent-line col)
  2066. (viper-yank-last-insertion))
  2067. (end-of-line)
  2068. (newline 1)
  2069. (viper-indent-line col)
  2070. (viper-change-state-to-insert)))))
  2071. (defun viper-Open-line (arg)
  2072. "Open line above."
  2073. (interactive "P")
  2074. (viper-set-complex-command-for-undo)
  2075. (let ((val (viper-p-val arg))
  2076. ;;(com (viper-getcom arg))
  2077. )
  2078. (viper-set-destructive-command (list 'viper-Open-line val ?r nil nil nil))
  2079. (let ((col (current-indentation)))
  2080. (if (eq viper-intermediate-command 'viper-repeat)
  2081. (viper-loop val
  2082. (beginning-of-line)
  2083. (open-line 1)
  2084. (viper-indent-line col)
  2085. (viper-yank-last-insertion))
  2086. (beginning-of-line)
  2087. (open-line 1)
  2088. (viper-indent-line col)
  2089. (viper-change-state-to-insert)))))
  2090. (defun viper-open-line-at-point (arg)
  2091. "Open line at point."
  2092. (interactive "P")
  2093. (viper-set-complex-command-for-undo)
  2094. (let ((val (viper-p-val arg))
  2095. ;;(com (viper-getcom arg))
  2096. )
  2097. (viper-set-destructive-command
  2098. (list 'viper-open-line-at-point val ?r nil nil nil))
  2099. (if (eq viper-intermediate-command 'viper-repeat)
  2100. (viper-loop val
  2101. (open-line 1)
  2102. (viper-yank-last-insertion))
  2103. (open-line 1)
  2104. (viper-change-state-to-insert))))
  2105. ;; bound to s
  2106. (defun viper-substitute (arg)
  2107. "Substitute characters."
  2108. (interactive "P")
  2109. (let ((val (viper-p-val arg))
  2110. ;;(com (viper-getcom arg))
  2111. )
  2112. (push-mark nil t)
  2113. (forward-char val)
  2114. (if (eq viper-intermediate-command 'viper-repeat)
  2115. (viper-change-subr (mark t) (point))
  2116. (viper-change (mark t) (point)))
  2117. ;; com is set to ?r when we repeat this command with dot
  2118. (viper-set-destructive-command (list 'viper-substitute val ?r nil nil nil))
  2119. ))
  2120. ;; Command bound to S
  2121. (defun viper-substitute-line (arg)
  2122. "Substitute lines."
  2123. (interactive "p")
  2124. (viper-set-complex-command-for-undo)
  2125. (viper-line (cons arg ?C)))
  2126. ;; Prepare for replace
  2127. (defun viper-start-replace ()
  2128. (setq viper-began-as-replace t
  2129. viper-sitting-in-replace t
  2130. viper-replace-chars-to-delete 0)
  2131. (add-hook
  2132. 'viper-after-change-functions 'viper-replace-mode-spy-after t 'local)
  2133. (add-hook
  2134. 'viper-before-change-functions 'viper-replace-mode-spy-before t 'local)
  2135. ;; this will get added repeatedly, but no harm
  2136. (add-hook 'after-change-functions 'viper-after-change-sentinel t)
  2137. (add-hook 'before-change-functions 'viper-before-change-sentinel t)
  2138. (viper-move-marker-locally
  2139. 'viper-last-posn-in-replace-region (viper-replace-start))
  2140. (add-hook
  2141. 'viper-post-command-hooks 'viper-replace-state-post-command-sentinel
  2142. t 'local)
  2143. (add-hook
  2144. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel t 'local)
  2145. ;; guard against a smarty who switched from R-replace to normal replace
  2146. (remove-hook
  2147. 'viper-post-command-hooks 'viper-R-state-post-command-sentinel 'local)
  2148. (if overwrite-mode (overwrite-mode -1))
  2149. )
  2150. (defun viper-replace-mode-spy-before (beg end)
  2151. (setq viper-replace-region-chars-deleted (viper-chars-in-region beg end))
  2152. )
  2153. ;; Invoked as an after-change-function to calculate how many chars have to be
  2154. ;; deleted. This function may be called several times within a single command,
  2155. ;; if this command performs several separate buffer changes. Therefore, if
  2156. ;; adds up the number of chars inserted and subtracts the number of chars
  2157. ;; deleted.
  2158. (defun viper-replace-mode-spy-after (beg end length)
  2159. (if (memq viper-intermediate-command
  2160. '(dabbrev-expand hippie-expand repeating-insertion-from-ring))
  2161. ;; Take special care of text insertion from insertion ring inside
  2162. ;; replacement overlays.
  2163. (progn
  2164. (setq viper-replace-chars-to-delete 0)
  2165. (viper-move-marker-locally
  2166. 'viper-last-posn-in-replace-region (point)))
  2167. (let* ((real-end (min end (viper-replace-end)))
  2168. (column-shift (- (save-excursion (goto-char real-end)
  2169. (current-column))
  2170. (save-excursion (goto-char beg)
  2171. (current-column))))
  2172. (chars-deleted 0))
  2173. (if (> length 0)
  2174. (setq chars-deleted viper-replace-region-chars-deleted))
  2175. (setq viper-replace-region-chars-deleted 0)
  2176. (setq viper-replace-chars-to-delete
  2177. (+ viper-replace-chars-to-delete
  2178. (-
  2179. ;; if column shift is bigger, due to a TAB insertion, take
  2180. ;; column-shift instead of the number of inserted chars
  2181. (max (viper-chars-in-region beg real-end)
  2182. ;; This test accounts for Chinese/Japanese/... chars,
  2183. ;; which occupy 2 columns instead of one. If we use
  2184. ;; column-shift here, we may delete two chars instead of
  2185. ;; one when the user types one Chinese character.
  2186. ;; Deleting two would be OK, if they were European chars,
  2187. ;; but it is not OK if they are Chinese chars.
  2188. ;; Since it is hard to
  2189. ;; figure out which characters are being deleted in any
  2190. ;; given region, we decided to treat Eastern and European
  2191. ;; characters equally, even though Eastern chars may
  2192. ;; occupy more columns.
  2193. (if (memq this-command '(self-insert-command
  2194. quoted-insert viper-insert-tab))
  2195. column-shift
  2196. 0))
  2197. ;; the number of deleted chars
  2198. chars-deleted)))
  2199. (viper-move-marker-locally
  2200. 'viper-last-posn-in-replace-region
  2201. (max (if (> end (viper-replace-end)) (viper-replace-end) end)
  2202. (or (marker-position viper-last-posn-in-replace-region)
  2203. (viper-replace-start))
  2204. ))
  2205. )))
  2206. ;; Delete stuff between viper-last-posn-in-replace-region and the end of
  2207. ;; viper-replace-overlay-marker, if viper-last-posn-in-replace-region is within
  2208. ;; the overlay and current point is before the end of the overlay.
  2209. ;; Don't delete anything if current point is past the end of the overlay.
  2210. (defun viper-finish-change ()
  2211. (remove-hook
  2212. 'viper-after-change-functions 'viper-replace-mode-spy-after 'local)
  2213. (remove-hook
  2214. 'viper-before-change-functions 'viper-replace-mode-spy-before 'local)
  2215. (remove-hook
  2216. 'viper-post-command-hooks 'viper-replace-state-post-command-sentinel 'local)
  2217. (remove-hook
  2218. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel 'local)
  2219. (viper-restore-cursor-color 'after-replace-mode)
  2220. (setq viper-sitting-in-replace nil) ; just in case we'll need to know it
  2221. (save-excursion
  2222. (if (and viper-replace-overlay
  2223. (viper-pos-within-region viper-last-posn-in-replace-region
  2224. (viper-replace-start)
  2225. (viper-replace-end))
  2226. (< (point) (viper-replace-end)))
  2227. (delete-region
  2228. viper-last-posn-in-replace-region (viper-replace-end))))
  2229. (if (eq viper-current-state 'replace-state)
  2230. (viper-downgrade-to-insert))
  2231. ;; replace mode ended => nullify viper-last-posn-in-replace-region
  2232. (viper-move-marker-locally 'viper-last-posn-in-replace-region nil)
  2233. (viper-hide-replace-overlay)
  2234. (viper-refresh-mode-line)
  2235. (viper-put-string-on-kill-ring viper-last-replace-region)
  2236. )
  2237. ;; Make STRING be the first element of the kill ring.
  2238. (defun viper-put-string-on-kill-ring (string)
  2239. (setq kill-ring (cons string kill-ring))
  2240. (if (> (length kill-ring) kill-ring-max)
  2241. (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
  2242. (setq kill-ring-yank-pointer kill-ring))
  2243. (defun viper-finish-R-mode ()
  2244. (remove-hook
  2245. 'viper-post-command-hooks 'viper-R-state-post-command-sentinel 'local)
  2246. (remove-hook
  2247. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel 'local)
  2248. (viper-downgrade-to-insert))
  2249. (defun viper-start-R-mode ()
  2250. ;; Leave arg as 1, not t: XEmacs insists that it must be a pos number
  2251. (overwrite-mode 1)
  2252. (add-hook
  2253. 'viper-post-command-hooks 'viper-R-state-post-command-sentinel t 'local)
  2254. (add-hook
  2255. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel t 'local)
  2256. ;; guard against a smarty who switched from R-replace to normal replace
  2257. (remove-hook
  2258. 'viper-post-command-hooks 'viper-replace-state-post-command-sentinel 'local)
  2259. )
  2260. (defun viper-replace-state-exit-cmd ()
  2261. "Binding for keys that cause Replace state to switch to Vi or to Insert.
  2262. These keys are ESC, RET, and LineFeed."
  2263. (interactive)
  2264. (if overwrite-mode ; if in replace mode invoked via 'R'
  2265. (viper-finish-R-mode)
  2266. (viper-finish-change))
  2267. (let (com)
  2268. (if (eq this-command 'viper-intercept-ESC-key)
  2269. (setq com 'viper-exit-insert-state)
  2270. (viper-set-unread-command-events last-input-event)
  2271. (setq com (key-binding (viper-read-key-sequence nil))))
  2272. (condition-case conds
  2273. (command-execute com)
  2274. (error
  2275. (viper-message-conditions conds)))
  2276. )
  2277. (viper-hide-replace-overlay))
  2278. (defun viper-replace-state-carriage-return ()
  2279. "Carriage return in Viper replace state."
  2280. (interactive)
  2281. ;; If Emacs start supporting overlay maps, as it currently supports
  2282. ;; text-property maps, we could do away with viper-replace-minor-mode and
  2283. ;; just have keymap attached to replace overlay. Then the "if part" of this
  2284. ;; statement can be deleted.
  2285. (if (or (< (point) (viper-replace-start))
  2286. (> (point) (viper-replace-end)))
  2287. (let (viper-replace-minor-mode com)
  2288. (viper-set-unread-command-events last-input-event)
  2289. (setq com (key-binding (read-key-sequence nil)))
  2290. (condition-case conds
  2291. (command-execute com)
  2292. (error
  2293. (viper-message-conditions conds))))
  2294. (if (not viper-allow-multiline-replace-regions)
  2295. (viper-replace-state-exit-cmd)
  2296. (if (viper-same-line (point) (viper-replace-end))
  2297. (viper-replace-state-exit-cmd)
  2298. ;; delete the rest of line
  2299. (delete-region (point) (viper-line-pos 'end))
  2300. (save-excursion
  2301. (end-of-line)
  2302. (if (eobp) (error "Last line in buffer")))
  2303. ;; skip to the next line
  2304. (forward-line 1)
  2305. (back-to-indentation)
  2306. ))))
  2307. ;; This is the function bound to 'R'---unlimited replace.
  2308. ;; Similar to Emacs's own overwrite-mode.
  2309. (defun viper-overwrite (arg)
  2310. "Begin overwrite mode."
  2311. (interactive "P")
  2312. (let ((val (viper-p-val arg))
  2313. ;;(com (viper-getcom arg))
  2314. (len))
  2315. (viper-set-destructive-command (list 'viper-overwrite val ?r nil nil nil))
  2316. (if (eq viper-intermediate-command 'viper-repeat)
  2317. (progn
  2318. ;; Viper saves inserted text in viper-last-insertion
  2319. (setq len (length viper-last-insertion))
  2320. (delete-char (min len (- (point-max) (point) 1)))
  2321. (viper-loop val (viper-yank-last-insertion)))
  2322. (setq last-command 'viper-overwrite)
  2323. (viper-set-complex-command-for-undo)
  2324. (viper-set-replace-overlay (point) (viper-line-pos 'end))
  2325. (viper-change-state-to-replace)
  2326. )))
  2327. ;; line commands
  2328. (defun viper-line (arg)
  2329. (let ((val (car arg))
  2330. (com (cdr arg)))
  2331. (viper-move-marker-locally 'viper-com-point (point))
  2332. (if (not (eobp))
  2333. (viper-next-line-carefully (1- val)))
  2334. ;; the following ensures that dd, cc, D, yy will do the right thing on the
  2335. ;; last line of buffer when this line has no \n.
  2336. (viper-add-newline-at-eob-if-necessary)
  2337. (viper-execute-com 'viper-line val com))
  2338. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2339. )
  2340. (defun viper-yank-line (arg)
  2341. "Yank ARG lines (in Vi's sense)."
  2342. (interactive "P")
  2343. (let ((val (viper-p-val arg)))
  2344. (viper-line (cons val ?Y))))
  2345. ;; region commands
  2346. (defun viper-region (arg)
  2347. "Execute command on a region."
  2348. (interactive "P")
  2349. (let ((val (viper-P-val arg))
  2350. (com (viper-getcom arg)))
  2351. (viper-move-marker-locally 'viper-com-point (point))
  2352. (exchange-point-and-mark)
  2353. (viper-execute-com 'viper-region val com)))
  2354. (defun viper-Region (arg)
  2355. "Execute command on a Region."
  2356. (interactive "P")
  2357. (let ((val (viper-P-val arg))
  2358. (com (viper-getCom arg)))
  2359. (viper-move-marker-locally 'viper-com-point (point))
  2360. (exchange-point-and-mark)
  2361. (viper-execute-com 'viper-Region val com)))
  2362. (defun viper-replace-char (arg)
  2363. "Replace the following ARG chars by the character read."
  2364. (interactive "P")
  2365. (if (and (eolp) (bolp)) (error "No character to replace here"))
  2366. (let ((val (viper-p-val arg))
  2367. (com (viper-getcom arg)))
  2368. (viper-replace-char-subr com val)
  2369. (if (and (eolp) (not (bolp))) (forward-char 1))
  2370. (setq viper-this-command-keys
  2371. (format "%sr" (if (integerp arg) arg "")))
  2372. (viper-set-destructive-command
  2373. (list 'viper-replace-char val ?r nil viper-d-char nil))
  2374. ))
  2375. (defun viper-replace-char-subr (com arg)
  2376. (let ((inhibit-quit t)
  2377. char)
  2378. (viper-set-complex-command-for-undo)
  2379. (or (eq viper-intermediate-command 'viper-repeat)
  2380. (viper-special-read-and-insert-char))
  2381. (delete-char 1 t)
  2382. (setq char (if com viper-d-char (viper-char-at-pos 'backward)))
  2383. (if com (insert char))
  2384. (setq viper-d-char char)
  2385. (viper-loop (1- (if (> arg 0) arg (- arg)))
  2386. (delete-char 1 t)
  2387. (insert char))
  2388. (viper-adjust-undo)
  2389. (backward-char arg)
  2390. ))
  2391. ;; basic cursor movement. j, k, l, h commands.
  2392. (defun viper-forward-char (arg)
  2393. "Move point right ARG characters (left if ARG negative).
  2394. On reaching end of line, stop and signal error."
  2395. (interactive "P")
  2396. (viper-leave-region-active)
  2397. (let ((val (viper-p-val arg))
  2398. (com (viper-getcom arg)))
  2399. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2400. (if viper-ex-style-motion
  2401. (progn
  2402. ;; the boundary condition check gets weird here because
  2403. ;; forward-char may be the parameter of a delete, and 'dl' works
  2404. ;; just like 'x' for the last char on a line, so we have to allow
  2405. ;; the forward motion before the 'viper-execute-com', but, of
  2406. ;; course, 'dl' doesn't work on an empty line, so we have to
  2407. ;; catch that condition before 'viper-execute-com'
  2408. (if (and (eolp) (bolp)) (error "Viper bell") (forward-char val))
  2409. (if com (viper-execute-com 'viper-forward-char val com))
  2410. (if (eolp) (progn (backward-char 1) (error "Viper bell"))))
  2411. (forward-char val)
  2412. (if com (viper-execute-com 'viper-forward-char val com)))))
  2413. (defun viper-backward-char (arg)
  2414. "Move point left ARG characters (right if ARG negative).
  2415. On reaching beginning of line, stop and signal error."
  2416. (interactive "P")
  2417. (viper-leave-region-active)
  2418. (let ((val (viper-p-val arg))
  2419. (com (viper-getcom arg)))
  2420. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2421. (if viper-ex-style-motion
  2422. (progn
  2423. (if (bolp) (error "Viper bell") (backward-char val))
  2424. (if com (viper-execute-com 'viper-backward-char val com)))
  2425. (backward-char val)
  2426. (if com (viper-execute-com 'viper-backward-char val com)))))
  2427. ;; Like forward-char, but doesn't move at end of buffer.
  2428. ;; Returns distance traveled
  2429. ;; (positive or 0, if arg positive; negative if arg negative).
  2430. (defun viper-forward-char-carefully (&optional arg)
  2431. (setq arg (or arg 1))
  2432. (let ((pt (point)))
  2433. (condition-case nil
  2434. (forward-char arg)
  2435. (error nil))
  2436. (if (< (point) pt) ; arg was negative
  2437. (- (viper-chars-in-region pt (point)))
  2438. (viper-chars-in-region pt (point)))))
  2439. ;; Like backward-char, but doesn't move at beg of buffer.
  2440. ;; Returns distance traveled
  2441. ;; (negative or 0, if arg positive; positive if arg negative).
  2442. (defun viper-backward-char-carefully (&optional arg)
  2443. (setq arg (or arg 1))
  2444. (let ((pt (point)))
  2445. (condition-case nil
  2446. (backward-char arg)
  2447. (error nil))
  2448. (if (> (point) pt) ; arg was negative
  2449. (viper-chars-in-region pt (point))
  2450. (- (viper-chars-in-region pt (point))))))
  2451. (defun viper-next-line-carefully (arg)
  2452. (condition-case nil
  2453. ;; do not use forward-line! need to keep column
  2454. (let ((line-move-visual nil))
  2455. (if (featurep 'emacs)
  2456. (with-no-warnings (next-line arg))
  2457. (next-line arg)))
  2458. (error nil)))
  2459. ;;; Word command
  2460. ;; Words are formed from alpha's and nonalphas - <sp>,\t\n are separators for
  2461. ;; word movement. When executed with a destructive command, \n is usually left
  2462. ;; untouched for the last word. Viper uses syntax table to determine what is a
  2463. ;; word and what is a separator. However, \n is always a separator. Also, if
  2464. ;; viper-syntax-preference is 'vi, then `_' is part of the word.
  2465. ;; skip only one \n
  2466. (defun viper-skip-separators (forward)
  2467. (if forward
  2468. (progn
  2469. (viper-skip-all-separators-forward 'within-line)
  2470. (if (looking-at "\n")
  2471. (progn
  2472. (forward-char)
  2473. (viper-skip-all-separators-forward 'within-line))))
  2474. ;; check for eob and white space before it. move off of eob
  2475. (if (and (eobp) (save-excursion
  2476. (viper-backward-char-carefully)
  2477. (viper-looking-at-separator)))
  2478. (viper-backward-char-carefully))
  2479. (viper-skip-all-separators-backward 'within-line)
  2480. (viper-backward-char-carefully)
  2481. (if (looking-at "\n")
  2482. (viper-skip-all-separators-backward 'within-line)
  2483. (or (viper-looking-at-separator) (forward-char)))))
  2484. (defun viper-forward-word-kernel (val)
  2485. (while (> val 0)
  2486. (cond ((viper-looking-at-alpha)
  2487. (viper-skip-alpha-forward "_")
  2488. (viper-skip-separators t))
  2489. ((viper-looking-at-separator)
  2490. (viper-skip-separators t))
  2491. ((not (viper-looking-at-alphasep))
  2492. (viper-skip-nonalphasep-forward)
  2493. (viper-skip-separators t)))
  2494. (setq val (1- val))))
  2495. ;; first skip non-newline separators backward, then skip \n. Then, if TWICE is
  2496. ;; non-nil, skip non-\n back again, but don't overshoot the limit LIM.
  2497. (defun viper-separator-skipback-special (twice lim)
  2498. (let ((prev-char (viper-char-at-pos 'backward))
  2499. (saved-point (point)))
  2500. ;; skip non-newline separators backward
  2501. (while (and (not (viper-memq-char prev-char '(nil \n)))
  2502. (< lim (point))
  2503. ;; must be non-newline separator
  2504. (if (eq viper-syntax-preference 'strict-vi)
  2505. (viper-memq-char prev-char '(?\ ?\t))
  2506. (viper-memq-char (char-syntax prev-char) '(?\ ?-))))
  2507. (viper-backward-char-carefully)
  2508. (setq prev-char (viper-char-at-pos 'backward)))
  2509. (if (and (< lim (point)) (eq prev-char ?\n))
  2510. (backward-char)
  2511. ;; If we skipped to the next word and the prefix of this line doesn't
  2512. ;; consist of separators preceded by a newline, then don't skip backwards
  2513. ;; at all.
  2514. (goto-char saved-point))
  2515. (setq prev-char (viper-char-at-pos 'backward))
  2516. ;; skip again, but make sure we don't overshoot the limit
  2517. (if twice
  2518. (while (and (not (viper-memq-char prev-char '(nil \n)))
  2519. (< lim (point))
  2520. ;; must be non-newline separator
  2521. (if (eq viper-syntax-preference 'strict-vi)
  2522. (viper-memq-char prev-char '(?\ ?\t))
  2523. (viper-memq-char (char-syntax prev-char) '(?\ ?-))))
  2524. (viper-backward-char-carefully)
  2525. (setq prev-char (viper-char-at-pos 'backward))))
  2526. (if (= (point) lim)
  2527. (viper-forward-char-carefully))
  2528. ))
  2529. (defun viper-forward-word (arg)
  2530. "Forward word."
  2531. (interactive "P")
  2532. (viper-leave-region-active)
  2533. (let ((val (viper-p-val arg))
  2534. (com (viper-getcom arg)))
  2535. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2536. (viper-forward-word-kernel val)
  2537. (if com
  2538. (progn
  2539. (cond ((viper-char-equal com ?c)
  2540. (viper-separator-skipback-special 'twice viper-com-point))
  2541. ;; Yank words including the whitespace, but not newline
  2542. ((viper-char-equal com ?y)
  2543. (viper-separator-skipback-special nil viper-com-point))
  2544. ((viper-dotable-command-p com)
  2545. (viper-separator-skipback-special nil viper-com-point)))
  2546. (viper-execute-com 'viper-forward-word val com)))
  2547. ))
  2548. (defun viper-forward-Word (arg)
  2549. "Forward word delimited by white characters."
  2550. (interactive "P")
  2551. (viper-leave-region-active)
  2552. (let ((val (viper-p-val arg))
  2553. (com (viper-getcom arg)))
  2554. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2555. (viper-loop val
  2556. (viper-skip-nonseparators 'forward)
  2557. (viper-skip-separators t))
  2558. (if com (progn
  2559. (cond ((viper-char-equal com ?c)
  2560. (viper-separator-skipback-special 'twice viper-com-point))
  2561. ;; Yank words including the whitespace, but not newline
  2562. ((viper-char-equal com ?y)
  2563. (viper-separator-skipback-special nil viper-com-point))
  2564. ((viper-dotable-command-p com)
  2565. (viper-separator-skipback-special nil viper-com-point)))
  2566. (viper-execute-com 'viper-forward-Word val com)))))
  2567. ;; this is a bit different from Vi, but Vi's end of word
  2568. ;; makes no sense whatsoever
  2569. (defun viper-end-of-word-kernel ()
  2570. (if (viper-end-of-word-p) (forward-char))
  2571. (if (viper-looking-at-separator)
  2572. (viper-skip-all-separators-forward))
  2573. (cond ((viper-looking-at-alpha) (viper-skip-alpha-forward "_"))
  2574. ((not (viper-looking-at-alphasep)) (viper-skip-nonalphasep-forward)))
  2575. (viper-backward-char-carefully))
  2576. (defun viper-end-of-word-p ()
  2577. (or (eobp)
  2578. (save-excursion
  2579. (cond ((viper-looking-at-alpha)
  2580. (forward-char)
  2581. (not (viper-looking-at-alpha)))
  2582. ((not (viper-looking-at-alphasep))
  2583. (forward-char)
  2584. (viper-looking-at-alphasep))))))
  2585. (defun viper-end-of-word (arg &optional careful)
  2586. "Move point to end of current word."
  2587. (interactive "P")
  2588. (viper-leave-region-active)
  2589. (let ((val (viper-p-val arg))
  2590. (com (viper-getcom arg)))
  2591. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2592. (viper-loop val (viper-end-of-word-kernel))
  2593. (if com
  2594. (progn
  2595. (forward-char)
  2596. (viper-execute-com 'viper-end-of-word val com)))))
  2597. (defun viper-end-of-Word (arg)
  2598. "Forward to end of word delimited by white character."
  2599. (interactive "P")
  2600. (viper-leave-region-active)
  2601. (let ((val (viper-p-val arg))
  2602. (com (viper-getcom arg)))
  2603. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2604. (viper-loop val
  2605. (viper-end-of-word-kernel)
  2606. (viper-skip-nonseparators 'forward)
  2607. (backward-char))
  2608. (if com
  2609. (progn
  2610. (forward-char)
  2611. (viper-execute-com 'viper-end-of-Word val com)))))
  2612. (defun viper-backward-word-kernel (val)
  2613. (while (> val 0)
  2614. (viper-backward-char-carefully)
  2615. (cond ((viper-looking-at-alpha)
  2616. (viper-skip-alpha-backward "_"))
  2617. ((viper-looking-at-separator)
  2618. (forward-char)
  2619. (viper-skip-separators nil)
  2620. (viper-backward-char-carefully)
  2621. (cond ((viper-looking-at-alpha)
  2622. (viper-skip-alpha-backward "_"))
  2623. ((not (viper-looking-at-alphasep))
  2624. (viper-skip-nonalphasep-backward))
  2625. ((bobp)) ; could still be at separator, but at beg of buffer
  2626. (t (forward-char))))
  2627. ((not (viper-looking-at-alphasep))
  2628. (viper-skip-nonalphasep-backward)))
  2629. (setq val (1- val))))
  2630. (defun viper-backward-word (arg)
  2631. "Backward word."
  2632. (interactive "P")
  2633. (viper-leave-region-active)
  2634. (let ((val (viper-p-val arg))
  2635. (com (viper-getcom arg)))
  2636. (if com
  2637. (let (i)
  2638. (if (setq i (save-excursion (backward-char) (looking-at "\n")))
  2639. (backward-char))
  2640. (viper-move-marker-locally 'viper-com-point (point))
  2641. (if i (forward-char))))
  2642. (viper-backward-word-kernel val)
  2643. (if com (viper-execute-com 'viper-backward-word val com))))
  2644. (defun viper-backward-Word (arg)
  2645. "Backward word delimited by white character."
  2646. (interactive "P")
  2647. (viper-leave-region-active)
  2648. (let ((val (viper-p-val arg))
  2649. (com (viper-getcom arg)))
  2650. (if com
  2651. (let (i)
  2652. (if (setq i (save-excursion (backward-char) (looking-at "\n")))
  2653. (backward-char))
  2654. (viper-move-marker-locally 'viper-com-point (point))
  2655. (if i (forward-char))))
  2656. (viper-loop val
  2657. (viper-skip-separators nil) ; nil means backward here
  2658. (viper-skip-nonseparators 'backward))
  2659. (if com (viper-execute-com 'viper-backward-Word val com))))
  2660. ;; line commands
  2661. (defun viper-beginning-of-line (arg)
  2662. "Go to beginning of line."
  2663. (interactive "P")
  2664. (viper-leave-region-active)
  2665. (let ((val (viper-p-val arg))
  2666. (com (viper-getcom arg)))
  2667. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2668. (beginning-of-line val)
  2669. (if com (viper-execute-com 'viper-beginning-of-line val com))))
  2670. (defun viper-bol-and-skip-white (arg)
  2671. "Beginning of line at first non-white character."
  2672. (interactive "P")
  2673. (viper-leave-region-active)
  2674. (let ((val (viper-p-val arg))
  2675. (com (viper-getcom arg)))
  2676. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2677. (forward-to-indentation (1- val))
  2678. (if com (viper-execute-com 'viper-bol-and-skip-white val com))))
  2679. (defun viper-goto-eol (arg)
  2680. "Go to end of line."
  2681. (interactive "P")
  2682. (viper-leave-region-active)
  2683. (let ((val (viper-p-val arg))
  2684. (com (viper-getcom arg)))
  2685. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2686. (end-of-line val)
  2687. (if com (viper-execute-com 'viper-goto-eol val com))
  2688. (if viper-ex-style-motion
  2689. (if (and (eolp) (not (bolp))
  2690. ;; a fix for viper-change-to-eol
  2691. (not (equal viper-current-state 'insert-state)))
  2692. (backward-char 1)
  2693. ))))
  2694. (defun viper-goto-col (arg)
  2695. "Go to ARG's column."
  2696. (interactive "P")
  2697. (viper-leave-region-active)
  2698. (let ((val (viper-p-val arg))
  2699. (com (viper-getcom arg))
  2700. line-len)
  2701. (setq line-len
  2702. (viper-chars-in-region
  2703. (viper-line-pos 'start) (viper-line-pos 'end)))
  2704. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2705. (beginning-of-line)
  2706. (forward-char (1- (min line-len val)))
  2707. (while (> (current-column) (1- val))
  2708. (backward-char 1))
  2709. (if com (viper-execute-com 'viper-goto-col val com))
  2710. (save-excursion
  2711. (end-of-line)
  2712. (if (> val (current-column)) (error "Viper bell")))
  2713. ))
  2714. (defun viper-next-line (arg)
  2715. "Go to next line."
  2716. (interactive "P")
  2717. (viper-leave-region-active)
  2718. (let ((val (viper-p-val arg))
  2719. (com (viper-getCom arg)))
  2720. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2721. ;; do not use forward-line! need to keep column
  2722. (let ((line-move-visual nil))
  2723. (if (featurep 'emacs)
  2724. (with-no-warnings (next-line val))
  2725. (next-line val)))
  2726. (if viper-ex-style-motion
  2727. (if (and (eolp) (not (bolp))) (backward-char 1)))
  2728. (setq this-command 'next-line)
  2729. (if com (viper-execute-com 'viper-next-line val com))))
  2730. (declare-function widget-type "wid-edit" (widget))
  2731. (declare-function widget-button-press "wid-edit" (pos &optional event))
  2732. (declare-function viper-set-hooks "viper" ())
  2733. (defun viper-next-line-at-bol (arg)
  2734. "Next line at beginning of line.
  2735. If point is on a widget or a button, simulate clicking on that widget/button."
  2736. (interactive "P")
  2737. (let* ((field (get-char-property (point) 'field))
  2738. (button (get-char-property (point) 'button))
  2739. (doc (get-char-property (point) 'widget-doc))
  2740. (widget (or field button doc)))
  2741. (if (and widget
  2742. (if (symbolp widget)
  2743. (get widget 'widget-type)
  2744. (and (consp widget)
  2745. (get (widget-type widget) 'widget-type))))
  2746. (widget-button-press (point))
  2747. (if (and (fboundp 'button-at) (fboundp 'push-button) (button-at (point)))
  2748. (push-button)
  2749. ;; not a widget or a button
  2750. (viper-leave-region-active)
  2751. (save-excursion
  2752. (end-of-line)
  2753. (if (eobp) (error "Last line in buffer")))
  2754. (let ((val (viper-p-val arg))
  2755. (com (viper-getCom arg)))
  2756. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2757. (forward-line val)
  2758. (back-to-indentation)
  2759. (if com (viper-execute-com 'viper-next-line-at-bol val com)))))))
  2760. (defun viper-previous-line (arg)
  2761. "Go to previous line."
  2762. (interactive "P")
  2763. (viper-leave-region-active)
  2764. (let ((val (viper-p-val arg))
  2765. (com (viper-getCom arg)))
  2766. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2767. ;; do not use forward-line! need to keep column
  2768. (let ((line-move-visual nil))
  2769. (if (featurep 'emacs)
  2770. (with-no-warnings (previous-line val))
  2771. (previous-line val)))
  2772. (if viper-ex-style-motion
  2773. (if (and (eolp) (not (bolp))) (backward-char 1)))
  2774. (setq this-command 'previous-line)
  2775. (if com (viper-execute-com 'viper-previous-line val com))))
  2776. (defun viper-previous-line-at-bol (arg)
  2777. "Previous line at beginning of line."
  2778. (interactive "P")
  2779. (viper-leave-region-active)
  2780. (save-excursion
  2781. (beginning-of-line)
  2782. (if (bobp) (error "First line in buffer")))
  2783. (let ((val (viper-p-val arg))
  2784. (com (viper-getCom arg)))
  2785. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2786. (forward-line (- val))
  2787. (back-to-indentation)
  2788. (if com (viper-execute-com 'viper-previous-line val com))))
  2789. (defun viper-change-to-eol (arg)
  2790. "Change to end of line."
  2791. (interactive "P")
  2792. (viper-goto-eol (cons arg ?c)))
  2793. (defun viper-kill-line (arg)
  2794. "Delete line."
  2795. (interactive "P")
  2796. (viper-goto-eol (cons arg ?d)))
  2797. (defun viper-erase-line (arg)
  2798. "Erase line."
  2799. (interactive "P")
  2800. (viper-beginning-of-line (cons arg ?d)))
  2801. ;;; Moving around
  2802. (defun viper-goto-line (arg)
  2803. "Go to ARG's line. Without ARG go to end of buffer."
  2804. (interactive "P")
  2805. (let ((val (viper-P-val arg))
  2806. (com (viper-getCom arg)))
  2807. (viper-move-marker-locally 'viper-com-point (point))
  2808. (viper-deactivate-mark)
  2809. (push-mark nil t)
  2810. (if (null val)
  2811. (goto-char (point-max))
  2812. (goto-char (point-min))
  2813. (forward-line (1- val)))
  2814. ;; positioning is done twice: before and after command execution
  2815. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2816. (back-to-indentation)
  2817. (if com (viper-execute-com 'viper-goto-line val com))
  2818. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2819. (back-to-indentation)
  2820. ))
  2821. ;; Find ARG's occurrence of CHAR on the current line.
  2822. ;; If FORWARD then search is forward, otherwise backward. OFFSET is used to
  2823. ;; adjust point after search.
  2824. (defun viper-find-char (arg char forward offset)
  2825. (or (char-or-string-p char) (error "Viper bell"))
  2826. (let ((arg (if forward arg (- arg)))
  2827. (cmd (if (eq viper-intermediate-command 'viper-repeat)
  2828. (nth 5 viper-d-com)
  2829. (viper-array-to-string (this-command-keys))))
  2830. point region-beg region-end)
  2831. (save-excursion
  2832. (save-restriction
  2833. (if (> arg 0) ; forward
  2834. (progn
  2835. (setq region-beg (point))
  2836. (if viper-allow-multiline-replace-regions
  2837. (viper-forward-paragraph 1)
  2838. (end-of-line))
  2839. (setq region-end (point)))
  2840. (setq region-end (point))
  2841. (if viper-allow-multiline-replace-regions
  2842. (viper-backward-paragraph 1)
  2843. (beginning-of-line))
  2844. (setq region-beg (point)))
  2845. (if (or (and (< arg 0)
  2846. (< (- region-end region-beg)
  2847. (if viper-allow-multiline-replace-regions
  2848. 2 1))
  2849. (bolp))
  2850. (and (> arg 0)
  2851. (< (- region-end region-beg)
  2852. (if viper-allow-multiline-replace-regions
  2853. 3 2))
  2854. (eolp)))
  2855. (error "Command `%s': At %s of %s"
  2856. cmd
  2857. (if (> arg 0) "end" "beginning")
  2858. (if viper-allow-multiline-replace-regions
  2859. "paragraph" "line")))
  2860. (narrow-to-region region-beg region-end)
  2861. ;; if arg > 0, point is forwarded before search.
  2862. (if (> arg 0) (goto-char (1+ (point-min)))
  2863. (goto-char (point-max)))
  2864. (if (let ((case-fold-search nil))
  2865. (search-forward (char-to-string char) nil 0 arg))
  2866. (setq point (point))
  2867. (error "Command `%s': `%c' not found" cmd char))))
  2868. (goto-char point)
  2869. (if (> arg 0)
  2870. (backward-char (if offset 2 1))
  2871. (forward-char (if offset 1 0)))))
  2872. (defun viper-find-char-forward (arg)
  2873. "Find char on the line.
  2874. If called interactively read the char to find from the terminal, and if
  2875. called from viper-repeat, the char last used is used. This behavior is
  2876. controlled by the sign of prefix numeric value."
  2877. (interactive "P")
  2878. (let ((val (viper-p-val arg))
  2879. (com (viper-getcom arg))
  2880. (cmd-representation (nth 5 viper-d-com)))
  2881. (if (> val 0)
  2882. ;; this means that the function was called interactively
  2883. (setq viper-f-char (read-char)
  2884. viper-f-forward t
  2885. viper-f-offset nil)
  2886. ;; viper-repeat --- set viper-F-char from command-keys
  2887. (setq viper-F-char (if (stringp cmd-representation)
  2888. (viper-seq-last-elt cmd-representation)
  2889. viper-F-char)
  2890. viper-f-char viper-F-char)
  2891. (setq val (- val)))
  2892. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2893. (viper-find-char
  2894. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) t nil)
  2895. (setq val (- val))
  2896. (if com
  2897. (progn
  2898. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2899. (forward-char)
  2900. (viper-execute-com 'viper-find-char-forward val com)))))
  2901. (defun viper-goto-char-forward (arg)
  2902. "Go up to char ARG forward on line."
  2903. (interactive "P")
  2904. (let ((val (viper-p-val arg))
  2905. (com (viper-getcom arg))
  2906. (cmd-representation (nth 5 viper-d-com)))
  2907. (if (> val 0)
  2908. ;; this means that the function was called interactively
  2909. (setq viper-f-char (read-char)
  2910. viper-f-forward t
  2911. viper-f-offset t)
  2912. ;; viper-repeat --- set viper-F-char from command-keys
  2913. (setq viper-F-char (if (stringp cmd-representation)
  2914. (viper-seq-last-elt cmd-representation)
  2915. viper-F-char)
  2916. viper-f-char viper-F-char)
  2917. (setq val (- val)))
  2918. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2919. (viper-find-char
  2920. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) t t)
  2921. (setq val (- val))
  2922. (if com
  2923. (progn
  2924. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2925. (forward-char)
  2926. (viper-execute-com 'viper-goto-char-forward val com)))))
  2927. (defun viper-find-char-backward (arg)
  2928. "Find char ARG on line backward."
  2929. (interactive "P")
  2930. (let ((val (viper-p-val arg))
  2931. (com (viper-getcom arg))
  2932. (cmd-representation (nth 5 viper-d-com)))
  2933. (if (> val 0)
  2934. ;; this means that the function was called interactively
  2935. (setq viper-f-char (read-char)
  2936. viper-f-forward nil
  2937. viper-f-offset nil)
  2938. ;; viper-repeat --- set viper-F-char from command-keys
  2939. (setq viper-F-char (if (stringp cmd-representation)
  2940. (viper-seq-last-elt cmd-representation)
  2941. viper-F-char)
  2942. viper-f-char viper-F-char)
  2943. (setq val (- val)))
  2944. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2945. (viper-find-char
  2946. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) nil nil)
  2947. (setq val (- val))
  2948. (if com
  2949. (progn
  2950. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2951. (viper-execute-com 'viper-find-char-backward val com)))))
  2952. (defun viper-goto-char-backward (arg)
  2953. "Go up to char ARG backward on line."
  2954. (interactive "P")
  2955. (let ((val (viper-p-val arg))
  2956. (com (viper-getcom arg))
  2957. (cmd-representation (nth 5 viper-d-com)))
  2958. (if (> val 0)
  2959. ;; this means that the function was called interactively
  2960. (setq viper-f-char (read-char)
  2961. viper-f-forward nil
  2962. viper-f-offset t)
  2963. ;; viper-repeat --- set viper-F-char from command-keys
  2964. (setq viper-F-char (if (stringp cmd-representation)
  2965. (viper-seq-last-elt cmd-representation)
  2966. viper-F-char)
  2967. viper-f-char viper-F-char)
  2968. (setq val (- val)))
  2969. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2970. (viper-find-char
  2971. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) nil t)
  2972. (setq val (- val))
  2973. (if com
  2974. (progn
  2975. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2976. (viper-execute-com 'viper-goto-char-backward val com)))))
  2977. (defun viper-repeat-find (arg)
  2978. "Repeat previous find command."
  2979. (interactive "P")
  2980. (let ((val (viper-p-val arg))
  2981. (com (viper-getcom arg)))
  2982. (viper-deactivate-mark)
  2983. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2984. (viper-find-char val viper-f-char viper-f-forward viper-f-offset)
  2985. (if com
  2986. (progn
  2987. (if viper-f-forward (forward-char))
  2988. (viper-execute-com 'viper-repeat-find val com)))))
  2989. (defun viper-repeat-find-opposite (arg)
  2990. "Repeat previous find command in the opposite direction."
  2991. (interactive "P")
  2992. (let ((val (viper-p-val arg))
  2993. (com (viper-getcom arg)))
  2994. (viper-deactivate-mark)
  2995. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2996. (viper-find-char val viper-f-char (not viper-f-forward) viper-f-offset)
  2997. (if com
  2998. (progn
  2999. (if viper-f-forward (forward-char))
  3000. (viper-execute-com 'viper-repeat-find-opposite val com)))))
  3001. ;; window scrolling etc.
  3002. (defun viper-window-top (arg)
  3003. "Go to home window line."
  3004. (interactive "P")
  3005. (let ((val (viper-p-val arg))
  3006. (com (viper-getCom arg)))
  3007. (viper-leave-region-active)
  3008. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3009. (push-mark nil t)
  3010. (move-to-window-line (1- val))
  3011. ;; positioning is done twice: before and after command execution
  3012. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  3013. (back-to-indentation)
  3014. (if com (viper-execute-com 'viper-window-top val com))
  3015. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  3016. (back-to-indentation)
  3017. ))
  3018. (defun viper-window-middle (arg)
  3019. "Go to middle window line."
  3020. (interactive "P")
  3021. (let ((val (viper-p-val arg))
  3022. (com (viper-getCom arg)))
  3023. (viper-leave-region-active)
  3024. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3025. (push-mark nil t)
  3026. (move-to-window-line (+ (/ (1- (window-height)) 2) (1- val)))
  3027. ;; positioning is done twice: before and after command execution
  3028. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  3029. (back-to-indentation)
  3030. (if com (viper-execute-com 'viper-window-middle val com))
  3031. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  3032. (back-to-indentation)
  3033. ))
  3034. (defun viper-window-bottom (arg)
  3035. "Go to last window line."
  3036. (interactive "P")
  3037. (let ((val (viper-p-val arg))
  3038. (com (viper-getCom arg)))
  3039. (viper-leave-region-active)
  3040. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3041. (push-mark nil t)
  3042. (move-to-window-line (- val))
  3043. ;; positioning is done twice: before and after command execution
  3044. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  3045. (back-to-indentation)
  3046. (if com (viper-execute-com 'viper-window-bottom val com))
  3047. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  3048. (back-to-indentation)
  3049. ))
  3050. (defun viper-line-to-top (arg)
  3051. "Put current line on the home line."
  3052. (interactive "p")
  3053. (recenter (1- arg)))
  3054. (defun viper-line-to-middle (arg)
  3055. "Put current line on the middle line."
  3056. (interactive "p")
  3057. (recenter (+ (1- arg) (/ (1- (window-height)) 2))))
  3058. (defun viper-line-to-bottom (arg)
  3059. "Put current line on the last line."
  3060. (interactive "p")
  3061. (recenter (- (window-height) (1+ arg))))
  3062. ;; If point is within viper-search-scroll-threshold of window top or bottom,
  3063. ;; scroll up or down 1/7 of window height, depending on whether we are at the
  3064. ;; bottom or at the top of the window. This function is called by viper-search
  3065. ;; (which is called from viper-search-forward/backward/next). If the value of
  3066. ;; viper-search-scroll-threshold is negative - don't scroll.
  3067. (defun viper-adjust-window ()
  3068. (let ((win-height (if (featurep 'xemacs)
  3069. (window-displayed-height)
  3070. (1- (window-height)))) ; adjust for modeline
  3071. (pt (point))
  3072. at-top-p at-bottom-p
  3073. min-scroll direction)
  3074. (save-excursion
  3075. (move-to-window-line 0) ; top
  3076. (setq at-top-p
  3077. (<= (count-lines pt (point))
  3078. viper-search-scroll-threshold))
  3079. (move-to-window-line -1) ; bottom
  3080. (setq at-bottom-p
  3081. (<= (count-lines pt (point)) viper-search-scroll-threshold)))
  3082. (cond (at-top-p (setq min-scroll (1- viper-search-scroll-threshold)
  3083. direction 1))
  3084. (at-bottom-p (setq min-scroll (1+ viper-search-scroll-threshold)
  3085. direction -1)))
  3086. (if min-scroll
  3087. (recenter
  3088. (* (max min-scroll (/ win-height 7)) direction)))
  3089. ))
  3090. ;; paren match
  3091. ;; must correct this to only match ( to ) etc. On the other hand
  3092. ;; it is good that paren match gets confused, because that way you
  3093. ;; catch _all_ imbalances.
  3094. (defun viper-paren-match (arg)
  3095. "Go to the matching parenthesis."
  3096. (interactive "P")
  3097. (viper-leave-region-active)
  3098. (let ((com (viper-getcom arg))
  3099. (parse-sexp-ignore-comments viper-parse-sexp-ignore-comments)
  3100. anchor-point)
  3101. (if (integerp arg)
  3102. (if (or (> arg 99) (< arg 1))
  3103. (error "Prefix must be between 1 and 99")
  3104. (goto-char
  3105. (if (> (point-max) 80000)
  3106. (* (/ (point-max) 100) arg)
  3107. (/ (* (point-max) arg) 100)))
  3108. (back-to-indentation))
  3109. (let (beg-lim end-lim)
  3110. (if (and (eolp) (not (bolp))) (forward-char -1))
  3111. (if (not (looking-at "[][(){}]"))
  3112. (setq anchor-point (point)))
  3113. (setq beg-lim (point-at-bol)
  3114. end-lim (point-at-eol))
  3115. (cond ((re-search-forward "[][(){}]" end-lim t)
  3116. (backward-char) )
  3117. ((re-search-backward "[][(){}]" beg-lim t))
  3118. (t
  3119. (error "No matching character on line"))))
  3120. (cond ((looking-at "[\(\[{]")
  3121. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3122. (forward-sexp 1)
  3123. (if com
  3124. (viper-execute-com 'viper-paren-match nil com)
  3125. (backward-char)))
  3126. (anchor-point
  3127. (if com
  3128. (progn
  3129. (viper-move-marker-locally 'viper-com-point anchor-point)
  3130. (forward-char 1)
  3131. (viper-execute-com 'viper-paren-match nil com)
  3132. )))
  3133. ((looking-at "[])}]")
  3134. (forward-char)
  3135. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3136. (backward-sexp 1)
  3137. (if com (viper-execute-com 'viper-paren-match nil com)))
  3138. (t (error "Viper bell"))))))
  3139. (defun viper-toggle-parse-sexp-ignore-comments ()
  3140. (interactive)
  3141. (setq viper-parse-sexp-ignore-comments
  3142. (not viper-parse-sexp-ignore-comments))
  3143. (princ (format
  3144. "From now on, `%%' will %signore parentheses inside comment fields"
  3145. (if viper-parse-sexp-ignore-comments "" "NOT "))))
  3146. ;; sentence, paragraph and heading
  3147. (defun viper-forward-sentence (arg)
  3148. "Forward sentence."
  3149. (interactive "P")
  3150. (or (eq last-command this-command)
  3151. (push-mark nil t))
  3152. (let ((val (viper-p-val arg))
  3153. (com (viper-getcom arg)))
  3154. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3155. (forward-sentence val)
  3156. (if com (viper-execute-com 'viper-forward-sentence nil com))))
  3157. (defun viper-backward-sentence (arg)
  3158. "Backward sentence."
  3159. (interactive "P")
  3160. (or (eq last-command this-command)
  3161. (push-mark nil t))
  3162. (let ((val (viper-p-val arg))
  3163. (com (viper-getcom arg)))
  3164. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3165. (backward-sentence val)
  3166. (if com (viper-execute-com 'viper-backward-sentence nil com))))
  3167. (defun viper-forward-paragraph (arg)
  3168. "Forward paragraph."
  3169. (interactive "P")
  3170. (or (eq last-command this-command)
  3171. (push-mark nil t))
  3172. (let ((val (viper-p-val arg))
  3173. ;; if you want d} operate on whole lines, change viper-getcom to
  3174. ;; viper-getCom below
  3175. (com (viper-getcom arg)))
  3176. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3177. (forward-paragraph val)
  3178. (if com
  3179. (progn
  3180. (backward-char 1)
  3181. (viper-execute-com 'viper-forward-paragraph nil com)))))
  3182. (defun viper-backward-paragraph (arg)
  3183. "Backward paragraph."
  3184. (interactive "P")
  3185. (or (eq last-command this-command)
  3186. (push-mark nil t))
  3187. (let ((val (viper-p-val arg))
  3188. ;; if you want d{ operate on whole lines, change viper-getcom to
  3189. ;; viper-getCom below
  3190. (com (viper-getcom arg)))
  3191. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3192. (backward-paragraph val)
  3193. (if com
  3194. (progn
  3195. (forward-char 1)
  3196. (viper-execute-com 'viper-backward-paragraph nil com)
  3197. (backward-char 1)))))
  3198. ;; should be mode-specific
  3199. (defun viper-prev-heading (arg)
  3200. (interactive "P")
  3201. (let ((val (viper-p-val arg))
  3202. (com (viper-getCom arg)))
  3203. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3204. (re-search-backward viper-heading-start nil t val)
  3205. (goto-char (match-beginning 0))
  3206. (if com (viper-execute-com 'viper-prev-heading nil com))))
  3207. (defun viper-heading-end (arg)
  3208. (interactive "P")
  3209. (let ((val (viper-p-val arg))
  3210. (com (viper-getCom arg)))
  3211. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3212. (re-search-forward viper-heading-end nil t val)
  3213. (goto-char (match-beginning 0))
  3214. (if com (viper-execute-com 'viper-heading-end nil com))))
  3215. (defun viper-next-heading (arg)
  3216. (interactive "P")
  3217. (let ((val (viper-p-val arg))
  3218. (com (viper-getCom arg)))
  3219. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3220. (end-of-line)
  3221. (re-search-forward viper-heading-start nil t val)
  3222. (goto-char (match-beginning 0))
  3223. (if com (viper-execute-com 'viper-next-heading nil com))))
  3224. ;; scrolling
  3225. (defun viper-scroll-screen (arg)
  3226. "Scroll to next screen."
  3227. (interactive "p")
  3228. (condition-case nil
  3229. (if (> arg 0)
  3230. (while (> arg 0)
  3231. (scroll-up)
  3232. (setq arg (1- arg)))
  3233. (while (> 0 arg)
  3234. (scroll-down)
  3235. (setq arg (1+ arg))))
  3236. (error (beep 1)
  3237. (if (> arg 0)
  3238. (progn
  3239. (message "End of buffer")
  3240. (goto-char (point-max)))
  3241. (message "Beginning of buffer")
  3242. (goto-char (point-min))))
  3243. ))
  3244. (defun viper-scroll-screen-back (arg)
  3245. "Scroll to previous screen."
  3246. (interactive "p")
  3247. (viper-scroll-screen (- arg)))
  3248. (defun viper-scroll-down (arg)
  3249. "Pull down half screen."
  3250. (interactive "P")
  3251. (condition-case nil
  3252. (if (null arg)
  3253. (scroll-down (/ (window-height) 2))
  3254. (scroll-down arg))
  3255. (error (beep 1)
  3256. (message "Beginning of buffer")
  3257. (goto-char (point-min)))))
  3258. (defun viper-scroll-down-one (arg)
  3259. "Scroll up one line."
  3260. (interactive "p")
  3261. (scroll-down arg))
  3262. (defun viper-scroll-up (arg)
  3263. "Pull up half screen."
  3264. (interactive "P")
  3265. (condition-case nil
  3266. (if (null arg)
  3267. (scroll-up (/ (window-height) 2))
  3268. (scroll-up arg))
  3269. (error (beep 1)
  3270. (message "End of buffer")
  3271. (goto-char (point-max)))))
  3272. (defun viper-scroll-up-one (arg)
  3273. "Scroll down one line."
  3274. (interactive "p")
  3275. (scroll-up arg))
  3276. ;; searching
  3277. (defun viper-insert-isearch-string ()
  3278. "Insert `isearch' last search string."
  3279. (interactive)
  3280. (when isearch-string (insert isearch-string)))
  3281. (defun viper-if-string (prompt)
  3282. (if (memq viper-intermediate-command
  3283. '(viper-command-argument viper-digit-argument viper-repeat))
  3284. (setq viper-this-command-keys (this-command-keys)))
  3285. (let* ((keymap (let ((keymap (copy-keymap minibuffer-local-map)))
  3286. (define-key keymap [(control ?s)] 'viper-insert-isearch-string)
  3287. keymap))
  3288. (s (viper-read-string-with-history
  3289. prompt
  3290. nil ; no initial
  3291. 'viper-search-history
  3292. (car viper-search-history)
  3293. keymap)))
  3294. (if (not (string= s ""))
  3295. (setq viper-s-string s))))
  3296. (defun viper-toggle-search-style (arg)
  3297. "Toggle the value of viper-case-fold-search/viper-re-search.
  3298. Without prefix argument, will ask which search style to toggle. With prefix
  3299. arg 1, toggles viper-case-fold-search; with arg 2 toggles viper-re-search.
  3300. Although this function is bound to \\[viper-toggle-search-style], the most
  3301. convenient way to use it is to bind `//' to the macro
  3302. `1 M-x viper-toggle-search-style' and `///' to
  3303. `2 M-x viper-toggle-search-style'. In this way, hitting `//' quickly will
  3304. toggle case-fold-search and hitting `/' three times with toggle regexp
  3305. search. Macros are more convenient in this case because they don't affect
  3306. the Emacs binding of `/'."
  3307. (interactive "P")
  3308. (let (msg)
  3309. (cond ((or (eq arg 1)
  3310. (and (null arg)
  3311. (y-or-n-p (format "Search style: '%s'. Want '%s'? "
  3312. (if viper-case-fold-search
  3313. "case-insensitive" "case-sensitive")
  3314. (if viper-case-fold-search
  3315. "case-sensitive"
  3316. "case-insensitive")))))
  3317. (setq viper-case-fold-search (null viper-case-fold-search))
  3318. (if viper-case-fold-search
  3319. (setq msg "Search becomes case-insensitive")
  3320. (setq msg "Search becomes case-sensitive")))
  3321. ((or (eq arg 2)
  3322. (and (null arg)
  3323. (y-or-n-p (format "Search style: '%s'. Want '%s'? "
  3324. (if viper-re-search
  3325. "regexp-search" "vanilla-search")
  3326. (if viper-re-search
  3327. "vanilla-search"
  3328. "regexp-search")))))
  3329. (setq viper-re-search (null viper-re-search))
  3330. (if viper-re-search
  3331. (setq msg "Search becomes regexp-style")
  3332. (setq msg "Search becomes vanilla-style")))
  3333. (t
  3334. (setq msg "Search style remains unchanged")))
  3335. (princ msg t)))
  3336. (defun viper-set-searchstyle-toggling-macros (unset &optional major-mode)
  3337. "Set the macros for toggling the search style in Viper's vi-state.
  3338. The macro that toggles case sensitivity is bound to `//', and the one that
  3339. toggles regexp search is bound to `///'.
  3340. With a prefix argument, this function unsets the macros.
  3341. If MAJOR-MODE is set, set the macros only in that major mode."
  3342. (interactive "P")
  3343. (let (scope)
  3344. (if (and major-mode (symbolp major-mode))
  3345. (setq scope major-mode)
  3346. (setq scope 't))
  3347. (or noninteractive
  3348. (if (not unset)
  3349. (progn
  3350. ;; toggle case sensitivity in search
  3351. (viper-record-kbd-macro
  3352. "//" 'vi-state
  3353. [1 (meta x) v i p e r - t o g g l e - s e a r c h - s t y l e return]
  3354. scope)
  3355. ;; toggle regexp/vanilla search
  3356. (viper-record-kbd-macro
  3357. "///" 'vi-state
  3358. [2 (meta x) v i p e r - t o g g l e - s e a r c h - s t y l e return]
  3359. scope)
  3360. ;; XEmacs has no called-interactively-p
  3361. ;; (if (called-interactively-p 'interactive)
  3362. (if (interactive-p)
  3363. (message
  3364. "// and /// now toggle case-sensitivity and regexp search")))
  3365. (viper-unrecord-kbd-macro "//" 'vi-state)
  3366. (sit-for 2)
  3367. (viper-unrecord-kbd-macro "///" 'vi-state)))
  3368. ))
  3369. (defun viper-set-parsing-style-toggling-macro (unset)
  3370. "Set `%%%' to be a macro that toggles whether comment fields should be parsed for matching parentheses.
  3371. This is used in conjunction with the `%' command.
  3372. With a prefix argument, unsets the macro."
  3373. (interactive "P")
  3374. (or noninteractive
  3375. (if (not unset)
  3376. (progn
  3377. ;; Make %%% toggle parsing comments for matching parentheses
  3378. (viper-record-kbd-macro
  3379. "%%%" 'vi-state
  3380. [(meta x) v i p e r - t o g g l e - p a r s e - s e x p - i g n o r e - c o m m e n t s return]
  3381. 't)
  3382. ;; XEmacs has no called-interactively-p. And interactive-p
  3383. ;; works fine here.
  3384. ;; (if (called-interactively-p 'interactive)
  3385. (if (interactive-p)
  3386. (message
  3387. "%%%%%% now toggles whether comments should be parsed for matching parentheses")))
  3388. (viper-unrecord-kbd-macro "%%%" 'vi-state))))
  3389. (defun viper-set-emacs-state-searchstyle-macros (unset &optional arg-majormode)
  3390. "Set the macros for toggling the search style in Viper's emacs-state.
  3391. The macro that toggles case sensitivity is bound to `//', and the one that
  3392. toggles regexp search is bound to `///'.
  3393. With a prefix argument, this function unsets the macros.
  3394. If the optional prefix argument is non-nil and specifies a valid major mode,
  3395. this sets the macros only in the macros in that major mode. Otherwise,
  3396. the macros are set in the current major mode.
  3397. \(When unsetting the macros, the second argument has no effect.\)"
  3398. (interactive "P")
  3399. (or noninteractive
  3400. (if (not unset)
  3401. (progn
  3402. ;; toggle case sensitivity in search
  3403. (viper-record-kbd-macro
  3404. "//" 'emacs-state
  3405. [1 (meta x) v i p e r - t o g g l e - s e a r c h - s t y l e return]
  3406. (or arg-majormode major-mode))
  3407. ;; toggle regexp/vanilla search
  3408. (viper-record-kbd-macro
  3409. "///" 'emacs-state
  3410. [2 (meta x) v i p e r - t o g g l e - s e a r c h - s t y l e return]
  3411. (or arg-majormode major-mode))
  3412. ;; called-interactively-p does not work for
  3413. ;; XEmacs. interactive-p is ok here.
  3414. ;; (if (called-interactively-p 'interactive)
  3415. (if (interactive-p)
  3416. (message
  3417. "// and /// now toggle case-sensitivity and regexp search.")))
  3418. (viper-unrecord-kbd-macro "//" 'emacs-state)
  3419. (sit-for 2)
  3420. (viper-unrecord-kbd-macro "///" 'emacs-state))))
  3421. (defun viper-search-forward (arg)
  3422. "Search a string forward.
  3423. ARG is used to find the ARG's occurrence of the string.
  3424. Null string will repeat previous search."
  3425. (interactive "P")
  3426. (let ((val (viper-P-val arg))
  3427. (com (viper-getcom arg))
  3428. (old-str viper-s-string)
  3429. debug-on-error)
  3430. (setq viper-s-forward t)
  3431. (viper-if-string "/")
  3432. ;; this is not used at present, but may be used later
  3433. (if (or (not (equal old-str viper-s-string))
  3434. (not (markerp viper-local-search-start-marker))
  3435. (not (marker-buffer viper-local-search-start-marker)))
  3436. (setq viper-local-search-start-marker (point-marker)))
  3437. (viper-search viper-s-string t val)
  3438. (if com
  3439. (progn
  3440. (viper-move-marker-locally 'viper-com-point (mark t))
  3441. (viper-execute-com 'viper-search-next val com)))
  3442. ))
  3443. (defun viper-search-backward (arg)
  3444. "Search a string backward.
  3445. ARG is used to find the ARG's occurrence of the string.
  3446. Null string will repeat previous search."
  3447. (interactive "P")
  3448. (let ((val (viper-P-val arg))
  3449. (com (viper-getcom arg))
  3450. (old-str viper-s-string)
  3451. debug-on-error)
  3452. (setq viper-s-forward nil)
  3453. (viper-if-string "?")
  3454. ;; this is not used at present, but may be used later
  3455. (if (or (not (equal old-str viper-s-string))
  3456. (not (markerp viper-local-search-start-marker))
  3457. (not (marker-buffer viper-local-search-start-marker)))
  3458. (setq viper-local-search-start-marker (point-marker)))
  3459. (viper-search viper-s-string nil val)
  3460. (if com
  3461. (progn
  3462. (viper-move-marker-locally 'viper-com-point (mark t))
  3463. (viper-execute-com 'viper-search-next val com)))))
  3464. ;; Search for COUNT's occurrence of STRING.
  3465. ;; Search is forward if FORWARD is non-nil, otherwise backward.
  3466. ;; INIT-POINT is the position where search is to start.
  3467. ;; Arguments:
  3468. ;; (STRING FORW COUNT &optional NO-OFFSET INIT-POINT LIMIT FAIL-IF-NOT-FOUND)
  3469. (defun viper-search (string forward arg
  3470. &optional no-offset init-point fail-if-not-found)
  3471. (if (not (equal string ""))
  3472. (let ((val (viper-p-val arg))
  3473. (com (viper-getcom arg))
  3474. (offset (not no-offset))
  3475. (case-fold-search viper-case-fold-search)
  3476. (start-point (or init-point (point))))
  3477. (viper-deactivate-mark)
  3478. (if forward
  3479. (condition-case nil
  3480. (progn
  3481. (if offset (viper-forward-char-carefully))
  3482. (if viper-re-search
  3483. (progn
  3484. (re-search-forward string nil nil val)
  3485. (re-search-backward string))
  3486. (search-forward string nil nil val)
  3487. (search-backward string))
  3488. (if (not (equal start-point (point)))
  3489. (push-mark start-point t)))
  3490. (search-failed
  3491. (if (and (not fail-if-not-found) viper-search-wrap-around)
  3492. (progn
  3493. (message "Search wrapped around BOTTOM of buffer")
  3494. (goto-char (point-min))
  3495. (viper-search string forward (cons 1 com) t start-point 'fail)
  3496. ;; don't wait in macros
  3497. (or executing-kbd-macro
  3498. (memq viper-intermediate-command
  3499. '(viper-repeat
  3500. viper-digit-argument
  3501. viper-command-argument))
  3502. (sit-for 2))
  3503. ;; delete the wrap-around message
  3504. (message "")
  3505. )
  3506. (goto-char start-point)
  3507. (error "`%s': %s not found"
  3508. string
  3509. (if viper-re-search "Pattern" "String"))
  3510. )))
  3511. ;; backward
  3512. (condition-case nil
  3513. (progn
  3514. (if viper-re-search
  3515. (re-search-backward string nil nil val)
  3516. (search-backward string nil nil val))
  3517. (if (not (equal start-point (point)))
  3518. (push-mark start-point t)))
  3519. (search-failed
  3520. (if (and (not fail-if-not-found) viper-search-wrap-around)
  3521. (progn
  3522. (message "Search wrapped around TOP of buffer")
  3523. (goto-char (point-max))
  3524. (viper-search string forward (cons 1 com) t start-point 'fail)
  3525. ;; don't wait in macros
  3526. (or executing-kbd-macro
  3527. (memq viper-intermediate-command
  3528. '(viper-repeat
  3529. viper-digit-argument
  3530. viper-command-argument))
  3531. (sit-for 2))
  3532. ;; delete the wrap-around message
  3533. (message "")
  3534. )
  3535. (goto-char start-point)
  3536. (error "`%s': %s not found"
  3537. string
  3538. (if viper-re-search "Pattern" "String"))
  3539. ))))
  3540. ;; pull up or down if at top/bottom of window
  3541. (viper-adjust-window)
  3542. ;; highlight the result of search
  3543. ;; don't wait and don't highlight in macros
  3544. (or executing-kbd-macro
  3545. (memq viper-intermediate-command
  3546. '(viper-repeat viper-digit-argument viper-command-argument))
  3547. (viper-flash-search-pattern))
  3548. )))
  3549. (defun viper-search-next (arg)
  3550. "Repeat previous search."
  3551. (interactive "P")
  3552. (let ((val (viper-p-val arg))
  3553. (com (viper-getcom arg))
  3554. debug-on-error)
  3555. (if (or (null viper-s-string) (string= viper-s-string ""))
  3556. (error viper-NoPrevSearch))
  3557. (viper-search viper-s-string viper-s-forward arg)
  3558. (if com
  3559. (progn
  3560. (viper-move-marker-locally 'viper-com-point (mark t))
  3561. (viper-execute-com 'viper-search-next val com)))))
  3562. (defun viper-search-Next (arg)
  3563. "Repeat previous search in the reverse direction."
  3564. (interactive "P")
  3565. (let ((val (viper-p-val arg))
  3566. (com (viper-getcom arg))
  3567. debug-on-error)
  3568. (if (null viper-s-string) (error viper-NoPrevSearch))
  3569. (viper-search viper-s-string (not viper-s-forward) arg)
  3570. (if com
  3571. (progn
  3572. (viper-move-marker-locally 'viper-com-point (mark t))
  3573. (viper-execute-com 'viper-search-Next val com)))))
  3574. ;; Search contents of buffer defined by one of Viper's motion commands.
  3575. ;; Repeatable via `n' and `N'.
  3576. (defun viper-buffer-search-enable (&optional c)
  3577. (cond (c (setq viper-buffer-search-char c))
  3578. ((null viper-buffer-search-char)
  3579. ;; ?g acts as a default value for viper-buffer-search-char
  3580. (setq viper-buffer-search-char ?g)))
  3581. (define-key viper-vi-basic-map
  3582. (cond ((viper-characterp viper-buffer-search-char)
  3583. (char-to-string viper-buffer-search-char))
  3584. (t (error "viper-buffer-search-char: wrong value type, %S"
  3585. viper-buffer-search-char)))
  3586. 'viper-command-argument)
  3587. (aset viper-exec-array viper-buffer-search-char 'viper-exec-buffer-search)
  3588. (setq viper-prefix-commands
  3589. (cons viper-buffer-search-char viper-prefix-commands)))
  3590. ;; This is a Viper wrapper for isearch-forward.
  3591. (defun viper-isearch-forward (arg)
  3592. "Do incremental search forward."
  3593. (interactive "P")
  3594. ;; emacs bug workaround
  3595. (if (listp arg) (setq arg (car arg)))
  3596. (viper-exec-form-in-emacs (list 'isearch-forward arg)))
  3597. ;; This is a Viper wrapper for isearch-backward."
  3598. (defun viper-isearch-backward (arg)
  3599. "Do incremental search backward."
  3600. (interactive "P")
  3601. ;; emacs bug workaround
  3602. (if (listp arg) (setq arg (car arg)))
  3603. (viper-exec-form-in-emacs (list 'isearch-backward arg)))
  3604. ;; visiting and killing files, buffers
  3605. (defun viper-switch-to-buffer ()
  3606. "Switch to buffer in the current window."
  3607. (interactive)
  3608. (let ((other-buffer (other-buffer (current-buffer)))
  3609. buffer)
  3610. (setq buffer
  3611. (funcall viper-read-buffer-function
  3612. "Switch to buffer in this window: " other-buffer))
  3613. (switch-to-buffer buffer)))
  3614. (defun viper-switch-to-buffer-other-window ()
  3615. "Switch to buffer in another window."
  3616. (interactive)
  3617. (let ((other-buffer (other-buffer (current-buffer)))
  3618. buffer)
  3619. (setq buffer
  3620. (funcall viper-read-buffer-function
  3621. "Switch to buffer in another window: " other-buffer))
  3622. (switch-to-buffer-other-window buffer)))
  3623. (defun viper-kill-buffer ()
  3624. "Kill a buffer."
  3625. (interactive)
  3626. (let (buffer buffer-name)
  3627. (setq buffer-name
  3628. (funcall viper-read-buffer-function
  3629. (format "Kill buffer \(%s\): "
  3630. (buffer-name (current-buffer)))))
  3631. (setq buffer
  3632. (if (null buffer-name)
  3633. (current-buffer)
  3634. (get-buffer buffer-name)))
  3635. (if (null buffer) (error "`%s': No such buffer" buffer-name))
  3636. (if (or (not (buffer-modified-p buffer))
  3637. (y-or-n-p
  3638. (format
  3639. "Buffer `%s' is modified, are you sure you want to kill it? "
  3640. buffer-name)))
  3641. (kill-buffer buffer)
  3642. (error "Buffer not killed"))))
  3643. ;; yank and pop
  3644. (defsubst viper-yank (text)
  3645. "Yank TEXT silently. This works correctly with Emacs's yank-pop command."
  3646. (insert text)
  3647. (setq this-command 'yank))
  3648. (defun viper-put-back (arg)
  3649. "Put back after point/below line."
  3650. (interactive "P")
  3651. (let ((val (viper-p-val arg))
  3652. (text (if viper-use-register
  3653. (cond ((viper-valid-register viper-use-register '(digit))
  3654. (current-kill
  3655. (- viper-use-register ?1) 'do-not-rotate))
  3656. ((viper-valid-register viper-use-register)
  3657. (get-register (downcase viper-use-register)))
  3658. (t (error viper-InvalidRegister viper-use-register)))
  3659. (current-kill 0)))
  3660. sv-point chars-inserted lines-inserted)
  3661. (if (null text)
  3662. (if viper-use-register
  3663. (let ((reg viper-use-register))
  3664. (setq viper-use-register nil)
  3665. (error viper-EmptyRegister reg))
  3666. (error "Viper bell")))
  3667. (setq viper-use-register nil)
  3668. (if (viper-end-with-a-newline-p text)
  3669. (progn
  3670. (end-of-line)
  3671. (if (eobp)
  3672. (insert "\n")
  3673. (forward-line 1))
  3674. (beginning-of-line))
  3675. (if (not (eolp)) (viper-forward-char-carefully)))
  3676. (set-marker (viper-mark-marker) (point) (current-buffer))
  3677. (viper-set-destructive-command
  3678. (list 'viper-put-back val nil viper-use-register nil nil))
  3679. (setq sv-point (point))
  3680. (viper-loop val (viper-yank text))
  3681. (setq chars-inserted (abs (- (point) sv-point))
  3682. lines-inserted (abs (count-lines (point) sv-point)))
  3683. (if (or (> chars-inserted viper-change-notification-threshold)
  3684. (> lines-inserted viper-change-notification-threshold))
  3685. (unless (viper-is-in-minibuffer)
  3686. (message "Inserted %d character(s), %d line(s)"
  3687. chars-inserted lines-inserted))))
  3688. ;; Vi puts cursor on the last char when the yanked text doesn't contain a
  3689. ;; newline; it leaves the cursor at the beginning when the text contains
  3690. ;; a newline
  3691. (if (viper-same-line (point) (mark))
  3692. (or (= (point) (mark)) (viper-backward-char-carefully))
  3693. (exchange-point-and-mark)
  3694. (if (bolp)
  3695. (back-to-indentation)))
  3696. (viper-deactivate-mark))
  3697. (defun viper-Put-back (arg)
  3698. "Put back at point/above line."
  3699. (interactive "P")
  3700. (let ((val (viper-p-val arg))
  3701. (text (if viper-use-register
  3702. (cond ((viper-valid-register viper-use-register '(digit))
  3703. (current-kill
  3704. (- viper-use-register ?1) 'do-not-rotate))
  3705. ((viper-valid-register viper-use-register)
  3706. (get-register (downcase viper-use-register)))
  3707. (t (error viper-InvalidRegister viper-use-register)))
  3708. (current-kill 0)))
  3709. sv-point chars-inserted lines-inserted)
  3710. (if (null text)
  3711. (if viper-use-register
  3712. (let ((reg viper-use-register))
  3713. (setq viper-use-register nil)
  3714. (error viper-EmptyRegister reg))
  3715. (error "Viper bell")))
  3716. (setq viper-use-register nil)
  3717. (if (viper-end-with-a-newline-p text) (beginning-of-line))
  3718. (viper-set-destructive-command
  3719. (list 'viper-Put-back val nil viper-use-register nil nil))
  3720. (set-marker (viper-mark-marker) (point) (current-buffer))
  3721. (setq sv-point (point))
  3722. (viper-loop val (viper-yank text))
  3723. (setq chars-inserted (abs (- (point) sv-point))
  3724. lines-inserted (abs (count-lines (point) sv-point)))
  3725. (if (or (> chars-inserted viper-change-notification-threshold)
  3726. (> lines-inserted viper-change-notification-threshold))
  3727. (unless (viper-is-in-minibuffer)
  3728. (message "Inserted %d character(s), %d line(s)"
  3729. chars-inserted lines-inserted))))
  3730. ;; Vi puts cursor on the last char when the yanked text doesn't contain a
  3731. ;; newline; it leaves the cursor at the beginning when the text contains
  3732. ;; a newline
  3733. (if (viper-same-line (point) (mark))
  3734. (or (= (point) (mark)) (viper-backward-char-carefully))
  3735. (exchange-point-and-mark)
  3736. (if (bolp)
  3737. (back-to-indentation)))
  3738. (viper-deactivate-mark))
  3739. ;; Copy region to kill-ring.
  3740. ;; If BEG and END do not belong to the same buffer, copy empty region.
  3741. (defun viper-copy-region-as-kill (beg end)
  3742. (condition-case nil
  3743. (copy-region-as-kill beg end)
  3744. (error (copy-region-as-kill beg beg))))
  3745. (defun viper-delete-char (arg)
  3746. "Delete next character."
  3747. (interactive "P")
  3748. (let ((val (viper-p-val arg))
  3749. end-del-pos)
  3750. (viper-set-destructive-command
  3751. (list 'viper-delete-char val nil nil nil nil))
  3752. (if (and viper-ex-style-editing
  3753. (> val (viper-chars-in-region (point) (viper-line-pos 'end))))
  3754. (setq val (viper-chars-in-region (point) (viper-line-pos 'end))))
  3755. (if (and viper-ex-style-motion (eolp))
  3756. (if (bolp) (error "Viper bell") (setq val 0))) ; not bol---simply back 1 ch
  3757. (save-excursion
  3758. (viper-forward-char-carefully val)
  3759. (setq end-del-pos (point)))
  3760. (if viper-use-register
  3761. (progn
  3762. (cond ((viper-valid-register viper-use-register '((Letter)))
  3763. (viper-append-to-register
  3764. (downcase viper-use-register) (point) end-del-pos))
  3765. ((viper-valid-register viper-use-register)
  3766. (copy-to-register
  3767. viper-use-register (point) end-del-pos nil))
  3768. (t (error viper-InvalidRegister viper-use-register)))
  3769. (setq viper-use-register nil)))
  3770. (delete-char val t)
  3771. (if viper-ex-style-motion
  3772. (if (and (eolp) (not (bolp))) (backward-char 1)))
  3773. ))
  3774. (defun viper-delete-backward-char (arg)
  3775. "Delete previous character. On reaching beginning of line, stop and beep."
  3776. (interactive "P")
  3777. (let ((val (viper-p-val arg))
  3778. end-del-pos)
  3779. (viper-set-destructive-command
  3780. (list 'viper-delete-backward-char val nil nil nil nil))
  3781. (if (and
  3782. viper-ex-style-editing
  3783. (> val (viper-chars-in-region (viper-line-pos 'start) (point))))
  3784. (setq val (viper-chars-in-region (viper-line-pos 'start) (point))))
  3785. (save-excursion
  3786. (viper-backward-char-carefully val)
  3787. (setq end-del-pos (point)))
  3788. (if viper-use-register
  3789. (progn
  3790. (cond ((viper-valid-register viper-use-register '(Letter))
  3791. (viper-append-to-register
  3792. (downcase viper-use-register) end-del-pos (point)))
  3793. ((viper-valid-register viper-use-register)
  3794. (copy-to-register
  3795. viper-use-register end-del-pos (point) nil))
  3796. (t (error viper-InvalidRegister viper-use-register)))
  3797. (setq viper-use-register nil)))
  3798. (if (and (bolp) viper-ex-style-editing)
  3799. (ding))
  3800. (delete-char (- val) t)))
  3801. (defun viper-del-backward-char-in-insert ()
  3802. "Delete 1 char backwards while in insert mode."
  3803. (interactive)
  3804. (if (and viper-ex-style-editing (bolp))
  3805. (beep 1)
  3806. ;; don't put on kill ring
  3807. (delete-char -1 nil)))
  3808. (defun viper-del-backward-char-in-replace ()
  3809. "Delete one character in replace mode.
  3810. If `viper-delete-backwards-in-replace' is t, then DEL key actually deletes
  3811. characters. If it is nil, then the cursor just moves backwards, similarly
  3812. to Vi. The variable `viper-ex-style-editing', if t, doesn't let the
  3813. cursor move past the beginning of line."
  3814. (interactive)
  3815. (cond (viper-delete-backwards-in-replace
  3816. (cond ((not (bolp))
  3817. ;; don't put on kill ring
  3818. (delete-char -1 nil))
  3819. (viper-ex-style-editing
  3820. (beep 1))
  3821. ((bobp)
  3822. (beep 1))
  3823. (t
  3824. ;; don't put on kill ring
  3825. (delete-char -1 nil))))
  3826. (viper-ex-style-editing
  3827. (if (bolp)
  3828. (beep 1)
  3829. (backward-char 1)))
  3830. (t
  3831. (backward-char 1))))
  3832. ;; join lines.
  3833. (defun viper-join-lines (arg)
  3834. "Join this line to next, if ARG is nil. Otherwise, join ARG lines."
  3835. (interactive "*P")
  3836. (let ((val (viper-P-val arg)))
  3837. (viper-set-destructive-command
  3838. (list 'viper-join-lines val nil nil nil nil))
  3839. (viper-loop (if (null val) 1 (1- val))
  3840. (end-of-line)
  3841. (if (not (eobp))
  3842. (progn
  3843. (forward-line 1)
  3844. (delete-region (point) (1- (point)))
  3845. (fixup-whitespace)
  3846. ;; fixup-whitespace sometimes does not leave space
  3847. ;; between objects, so we insert it as in Vi
  3848. (or (looking-at " ")
  3849. (insert " ")
  3850. (backward-char 1))
  3851. )))))
  3852. ;; Replace state
  3853. (defun viper-change (beg end)
  3854. (if (markerp beg) (setq beg (marker-position beg)))
  3855. (if (markerp end) (setq end (marker-position end)))
  3856. ;; beg is sometimes (mark t), which may be nil
  3857. (or beg (setq beg end))
  3858. (viper-set-complex-command-for-undo)
  3859. (if viper-use-register
  3860. (progn
  3861. (copy-to-register viper-use-register beg end nil)
  3862. (setq viper-use-register nil)))
  3863. (viper-set-replace-overlay beg end)
  3864. (setq last-command nil) ; separate repl text from prev kills
  3865. (if (= (viper-replace-start) (point-max))
  3866. (error "End of buffer"))
  3867. (setq viper-last-replace-region
  3868. (buffer-substring (viper-replace-start)
  3869. (viper-replace-end)))
  3870. ;; protect against error while inserting "@" and other disasters
  3871. ;; (e.g., read-only buff)
  3872. (condition-case conds
  3873. (if (or viper-allow-multiline-replace-regions
  3874. (viper-same-line (viper-replace-start)
  3875. (viper-replace-end)))
  3876. (progn
  3877. ;; tabs cause problems in replace, so untabify
  3878. (goto-char (viper-replace-end))
  3879. (insert-before-markers "@") ; put placeholder after the TAB
  3880. (untabify (viper-replace-start) (point))
  3881. ;; del @, don't put on kill ring
  3882. (delete-char -1)
  3883. (viper-set-replace-overlay-glyphs
  3884. viper-replace-region-start-delimiter
  3885. viper-replace-region-end-delimiter)
  3886. ;; this move takes care of the last posn in the overlay, which
  3887. ;; has to be shifted because of insert. We can't simply insert
  3888. ;; "$" before-markers because then overlay-start will shift the
  3889. ;; beginning of the overlay in case we are replacing a single
  3890. ;; character. This fixes the bug with `s' and `cl' commands.
  3891. (viper-move-replace-overlay (viper-replace-start) (point))
  3892. (goto-char (viper-replace-start))
  3893. (viper-change-state-to-replace t))
  3894. (kill-region (viper-replace-start)
  3895. (viper-replace-end))
  3896. (viper-hide-replace-overlay)
  3897. (viper-change-state-to-insert))
  3898. (error ;; make sure that the overlay doesn't stay.
  3899. ;; go back to the original point
  3900. (goto-char (viper-replace-start))
  3901. (viper-hide-replace-overlay)
  3902. (viper-message-conditions conds))))
  3903. (defun viper-change-subr (beg end)
  3904. ;; beg is sometimes (mark t), which may be nil
  3905. (or beg (setq beg end))
  3906. (if viper-use-register
  3907. (progn
  3908. (copy-to-register viper-use-register beg end nil)
  3909. (setq viper-use-register nil)))
  3910. (kill-region beg end)
  3911. (setq this-command 'viper-change)
  3912. (viper-yank-last-insertion))
  3913. (defun viper-toggle-case (arg)
  3914. "Toggle character case."
  3915. (interactive "P")
  3916. (let ((val (viper-p-val arg)) (c))
  3917. (viper-set-destructive-command
  3918. (list 'viper-toggle-case val nil nil nil nil))
  3919. (while (> val 0)
  3920. (setq c (following-char))
  3921. (delete-char 1 nil)
  3922. (if (eq c (upcase c))
  3923. (insert-char (downcase c) 1)
  3924. (insert-char (upcase c) 1))
  3925. (if (eolp) (backward-char 1))
  3926. (setq val (1- val)))))
  3927. ;; query replace
  3928. (defun viper-query-replace ()
  3929. "Query replace.
  3930. If a null string is supplied as the string to be replaced,
  3931. the query replace mode will toggle between string replace
  3932. and regexp replace."
  3933. (interactive)
  3934. (let (str)
  3935. (setq str (viper-read-string-with-history
  3936. (if viper-re-query-replace "Query replace regexp: "
  3937. "Query replace: ")
  3938. nil ; no initial
  3939. 'viper-replace1-history
  3940. (car viper-replace1-history) ; default
  3941. ))
  3942. (if (string= str "")
  3943. (progn
  3944. (setq viper-re-query-replace (not viper-re-query-replace))
  3945. (message "Query replace mode changed to %s"
  3946. (if viper-re-query-replace "regexp replace"
  3947. "string replace")))
  3948. (if viper-re-query-replace
  3949. (query-replace-regexp
  3950. str
  3951. (viper-read-string-with-history
  3952. (format "Query replace regexp `%s' with: " str)
  3953. nil ; no initial
  3954. 'viper-replace1-history
  3955. (car viper-replace1-history) ; default
  3956. ))
  3957. (query-replace
  3958. str
  3959. (viper-read-string-with-history
  3960. (format "Query replace `%s' with: " str)
  3961. nil ; no initial
  3962. 'viper-replace1-history
  3963. (car viper-replace1-history) ; default
  3964. ))))))
  3965. ;; marking
  3966. (defun viper-mark-beginning-of-buffer ()
  3967. "Mark beginning of buffer."
  3968. (interactive)
  3969. (push-mark (point))
  3970. (goto-char (point-min))
  3971. (exchange-point-and-mark)
  3972. (message "Mark set at the beginning of buffer"))
  3973. (defun viper-mark-end-of-buffer ()
  3974. "Mark end of buffer."
  3975. (interactive)
  3976. (push-mark (point))
  3977. (goto-char (point-max))
  3978. (exchange-point-and-mark)
  3979. (message "Mark set at the end of buffer"))
  3980. (defun viper-mark-point ()
  3981. "Set mark at point of buffer."
  3982. (interactive)
  3983. (let ((char (read-char)))
  3984. (cond ((and (<= ?a char) (<= char ?z))
  3985. (point-to-register (viper-int-to-char (1+ (- char ?a)))))
  3986. ((viper= char ?<) (viper-mark-beginning-of-buffer))
  3987. ((viper= char ?>) (viper-mark-end-of-buffer))
  3988. ((viper= char ?.) (viper-set-mark-if-necessary))
  3989. ((viper= char ?,) (viper-cycle-through-mark-ring))
  3990. ((viper= char ?^) (push-mark viper-saved-mark t t))
  3991. ((viper= char ?D) (mark-defun))
  3992. (t (error "Viper bell"))
  3993. )))
  3994. ;; Algorithm: If first invocation of this command save mark on ring, goto
  3995. ;; mark, M0, and pop the most recent elt from the mark ring into mark,
  3996. ;; making it into the new mark, M1.
  3997. ;; Push this mark back and set mark to the original point position, p1.
  3998. ;; So, if you hit '' or `` then you can return to p1.
  3999. ;;
  4000. ;; If repeated command, pop top elt from the ring into mark and
  4001. ;; jump there. This forgets the position, p1, and puts M1 back into mark.
  4002. ;; Then we save the current pos, which is M0, jump to M1 and pop M2 from
  4003. ;; the ring into mark. Push M2 back on the ring and set mark to M0.
  4004. ;; etc.
  4005. (defun viper-cycle-through-mark-ring ()
  4006. "Visit previous locations on the mark ring.
  4007. One can use `` and '' to temporarily jump 1 step back."
  4008. (let* ((sv-pt (point)))
  4009. ;; if repeated `m,' command, pop the previously saved mark.
  4010. ;; Prev saved mark is actually prev saved point. It is used if the
  4011. ;; user types `` or '' and is discarded
  4012. ;; from the mark ring by the next `m,' command.
  4013. ;; In any case, go to the previous or previously saved mark.
  4014. ;; Then push the current mark (popped off the ring) and set current
  4015. ;; point to be the mark. Current pt as mark is discarded by the next
  4016. ;; m, command.
  4017. (if (eq last-command 'viper-cycle-through-mark-ring)
  4018. ()
  4019. ;; save current mark if the first iteration
  4020. (setq mark-ring (delete (viper-mark-marker) mark-ring))
  4021. (if (mark t)
  4022. (push-mark (mark t) t)) )
  4023. (pop-mark)
  4024. (set-mark-command 1)
  4025. ;; don't duplicate mark on the ring
  4026. (setq mark-ring (delete (viper-mark-marker) mark-ring))
  4027. (push-mark sv-pt t)
  4028. (viper-deactivate-mark)
  4029. (setq this-command 'viper-cycle-through-mark-ring)
  4030. ))
  4031. (defun viper-goto-mark (arg)
  4032. "Go to mark."
  4033. (interactive "P")
  4034. (let ((char (read-char))
  4035. (com (viper-getcom arg)))
  4036. (viper-goto-mark-subr char com nil)))
  4037. (defun viper-goto-mark-and-skip-white (arg)
  4038. "Go to mark and skip to first non-white character on line."
  4039. (interactive "P")
  4040. (let ((char (read-char))
  4041. (com (viper-getCom arg)))
  4042. (viper-goto-mark-subr char com t)))
  4043. (defun viper-goto-mark-subr (char com skip-white)
  4044. (if (eobp)
  4045. (if (bobp)
  4046. (error "Empty buffer")
  4047. (backward-char 1)))
  4048. (cond ((viper-valid-register char '(letter))
  4049. (let* ((buff (current-buffer))
  4050. (reg (viper-int-to-char (1+ (- char ?a))))
  4051. (text-marker (get-register reg)))
  4052. ;; If marker points to file that had markers set (and those markers
  4053. ;; were saved (as e.g., in session.el), then restore those markers
  4054. (if (and (consp text-marker)
  4055. (eq (car text-marker) 'file-query)
  4056. (or (find-buffer-visiting (nth 1 text-marker))
  4057. (y-or-n-p (format "Visit file %s again? "
  4058. (nth 1 text-marker)))))
  4059. (save-excursion
  4060. (find-file (nth 1 text-marker))
  4061. (when (and (<= (nth 2 text-marker) (point-max))
  4062. (<= (point-min) (nth 2 text-marker)))
  4063. (setq text-marker (copy-marker (nth 2 text-marker)))
  4064. (set-register reg text-marker))))
  4065. (if com (viper-move-marker-locally 'viper-com-point (point)))
  4066. (if (not (viper-valid-marker text-marker))
  4067. (error viper-EmptyTextmarker char))
  4068. (if (and (viper-same-line (point) viper-last-jump)
  4069. (= (point) viper-last-jump-ignore))
  4070. (push-mark viper-last-jump t)
  4071. (push-mark nil t)) ; no msg
  4072. (viper-register-to-point reg)
  4073. (setq viper-last-jump (point-marker))
  4074. (cond (skip-white
  4075. (back-to-indentation)
  4076. (setq viper-last-jump-ignore (point))))
  4077. (if com
  4078. (if (equal buff (current-buffer))
  4079. (viper-execute-com (if skip-white
  4080. 'viper-goto-mark-and-skip-white
  4081. 'viper-goto-mark)
  4082. nil com)
  4083. (switch-to-buffer buff)
  4084. (goto-char viper-com-point)
  4085. (viper-change-state-to-vi)
  4086. (error "Viper bell")))))
  4087. ((and (not skip-white) (viper= char ?`))
  4088. (if com (viper-move-marker-locally 'viper-com-point (point)))
  4089. (if (and (viper-same-line (point) viper-last-jump)
  4090. (= (point) viper-last-jump-ignore))
  4091. (goto-char viper-last-jump))
  4092. (if (null (mark t)) (error "Mark is not set in this buffer"))
  4093. (if (= (point) (mark t)) (pop-mark))
  4094. (exchange-point-and-mark)
  4095. (setq viper-last-jump (point-marker)
  4096. viper-last-jump-ignore 0)
  4097. (if com (viper-execute-com 'viper-goto-mark nil com)))
  4098. ((and skip-white (viper= char ?'))
  4099. (if com (viper-move-marker-locally 'viper-com-point (point)))
  4100. (if (and (viper-same-line (point) viper-last-jump)
  4101. (= (point) viper-last-jump-ignore))
  4102. (goto-char viper-last-jump))
  4103. (if (= (point) (mark t)) (pop-mark))
  4104. (exchange-point-and-mark)
  4105. (setq viper-last-jump (point))
  4106. (back-to-indentation)
  4107. (setq viper-last-jump-ignore (point))
  4108. (if com (viper-execute-com 'viper-goto-mark-and-skip-white nil com)))
  4109. (t (error viper-InvalidTextmarker char))))
  4110. (defun viper-insert-tab ()
  4111. (interactive)
  4112. (insert-tab))
  4113. (defun viper-exchange-point-and-mark ()
  4114. (interactive)
  4115. (exchange-point-and-mark)
  4116. (back-to-indentation))
  4117. ;; Input Mode Indentation
  4118. ;; Returns t, if the string before point matches the regexp STR.
  4119. (defsubst viper-looking-back (str)
  4120. (and (save-excursion (re-search-backward str nil t))
  4121. (= (point) (match-end 0))))
  4122. (defun viper-forward-indent ()
  4123. "Indent forward -- `C-t' in Vi."
  4124. (interactive)
  4125. (setq viper-cted t)
  4126. (indent-to (+ (current-column) viper-shift-width)))
  4127. (defun viper-backward-indent ()
  4128. "Backtab, `C-d' in Vi."
  4129. (interactive)
  4130. (if viper-cted
  4131. (let ((p (point)) (c (current-column)) bol (indent t))
  4132. (if (viper-looking-back "[0^]")
  4133. (progn
  4134. (if (eq ?^ (preceding-char))
  4135. (setq viper-preserve-indent t))
  4136. (delete-char -1)
  4137. (setq p (point))
  4138. (setq indent nil)))
  4139. (setq bol (point-at-bol))
  4140. (if (re-search-backward "[^ \t]" bol 1) (forward-char))
  4141. (delete-region (point) p)
  4142. (if indent
  4143. (indent-to (- c viper-shift-width)))
  4144. (if (or (bolp) (viper-looking-back "[^ \t]"))
  4145. (setq viper-cted nil)))))
  4146. ;; do smart indent
  4147. (defun viper-indent-line (col)
  4148. (if viper-auto-indent
  4149. (progn
  4150. (setq viper-cted t)
  4151. (if (and viper-electric-mode
  4152. (not (memq major-mode '(fundamental-mode
  4153. text-mode
  4154. paragraph-indent-text-mode))))
  4155. (indent-according-to-mode)
  4156. (indent-to col)))))
  4157. (defun viper-autoindent ()
  4158. "Auto Indentation, Vi-style."
  4159. (interactive)
  4160. (let ((col (current-indentation)))
  4161. (if abbrev-mode (expand-abbrev))
  4162. (if viper-preserve-indent
  4163. (setq viper-preserve-indent nil)
  4164. (setq viper-current-indent col))
  4165. ;; don't leave whitespace lines around
  4166. (if (memq last-command
  4167. '(viper-autoindent
  4168. viper-open-line viper-Open-line
  4169. viper-replace-state-exit-cmd))
  4170. (indent-to-left-margin))
  4171. ;; use \n instead of newline, or else <Return> will move the insert point
  4172. ;;(newline 1)
  4173. (insert "\n")
  4174. (viper-indent-line viper-current-indent)
  4175. ))
  4176. ;; Viewing registers
  4177. (defun viper-ket-function (arg)
  4178. "Function called by \], the ket. View registers and call \]\]."
  4179. (interactive "P")
  4180. (let ((reg (read-char)))
  4181. (cond ((viper-valid-register reg '(letter Letter))
  4182. (view-register (downcase reg)))
  4183. ((viper-valid-register reg '(digit))
  4184. (let ((text (current-kill (- reg ?1) 'do-not-rotate)))
  4185. (with-output-to-temp-buffer " *viper-info*"
  4186. (princ (format "Register %c contains the string:\n" reg))
  4187. (princ text))
  4188. ))
  4189. ((viper= ?\] reg)
  4190. (viper-next-heading arg))
  4191. (t (error
  4192. viper-InvalidRegister reg)))))
  4193. (defun viper-brac-function (arg)
  4194. "Function called by \[, the brac. View textmarkers and call \[\[."
  4195. (interactive "P")
  4196. (let ((reg (read-char)))
  4197. (cond ((viper= ?\[ reg)
  4198. (viper-prev-heading arg))
  4199. ((viper= ?\] reg)
  4200. (viper-heading-end arg))
  4201. ((viper-valid-register reg '(letter))
  4202. (let* ((val (get-register (viper-int-to-char (1+ (- reg ?a)))))
  4203. (buf (if (not (markerp val))
  4204. (error viper-EmptyTextmarker reg)
  4205. (marker-buffer val)))
  4206. (pos (marker-position val))
  4207. line-no text (s pos) (e pos))
  4208. (with-output-to-temp-buffer " *viper-info*"
  4209. (if (and buf pos)
  4210. (progn
  4211. (with-current-buffer buf
  4212. (setq line-no (1+ (count-lines (point-min) val)))
  4213. (goto-char pos)
  4214. (beginning-of-line)
  4215. (if (re-search-backward "[^ \t]" nil t)
  4216. (setq s (point-at-bol)))
  4217. (goto-char pos)
  4218. (forward-line 1)
  4219. (if (re-search-forward "[^ \t]" nil t)
  4220. (progn
  4221. (end-of-line)
  4222. (setq e (point))))
  4223. (setq text (buffer-substring s e))
  4224. (setq text (format "%s<%c>%s"
  4225. (substring text 0 (- pos s))
  4226. reg (substring text (- pos s)))))
  4227. (princ
  4228. (format
  4229. "Textmarker `%c' is in buffer `%s' at line %d.\n"
  4230. reg (buffer-name buf) line-no))
  4231. (princ (format "Here is some text around %c:\n\n %s"
  4232. reg text)))
  4233. (princ (format viper-EmptyTextmarker reg))))
  4234. ))
  4235. (t (error viper-InvalidTextmarker reg)))))
  4236. (defun viper-delete-backward-word (arg)
  4237. "Delete previous word."
  4238. (interactive "p")
  4239. (save-excursion
  4240. (push-mark nil t)
  4241. (backward-word arg)
  4242. (delete-region (point) (mark t))
  4243. (pop-mark)))
  4244. ;; Get viper standard value of SYMBOL. If symbol is customized, get its
  4245. ;; standard value. Otherwise, get the value saved in the alist STORAGE. If
  4246. ;; STORAGE is nil, use viper-saved-user-settings.
  4247. (defun viper-standard-value (symbol &optional storage)
  4248. (or (eval (car (get symbol 'customized-value)))
  4249. (eval (car (get symbol 'saved-value)))
  4250. (nth 1 (assoc symbol (or storage viper-saved-user-settings)))))
  4251. (defun viper-set-expert-level (&optional dont-change-unless)
  4252. "Sets the expert level for a Viper user.
  4253. Can be called interactively to change (temporarily or permanently) the
  4254. current expert level.
  4255. The optional argument DONT-CHANGE-UNLESS, if not nil, says that
  4256. the level should not be changed, unless its current value is
  4257. meaningless (i.e., not one of 1,2,3,4,5).
  4258. User level determines the setting of Viper variables that are most
  4259. sensitive for VI-style look-and-feel."
  4260. (interactive)
  4261. (if (not (natnump viper-expert-level)) (setq viper-expert-level 0))
  4262. (save-window-excursion
  4263. (delete-other-windows)
  4264. ;; if 0 < viper-expert-level < viper-max-expert-level
  4265. ;; & dont-change-unless = t -- use it; else ask
  4266. (viper-ask-level dont-change-unless))
  4267. (setq viper-always t
  4268. viper-ex-style-motion t
  4269. viper-ex-style-editing t
  4270. viper-want-ctl-h-help nil)
  4271. (cond ((eq viper-expert-level 1) ; novice or beginner
  4272. (global-set-key ; in emacs-state
  4273. viper-toggle-key
  4274. (if (viper-window-display-p) 'viper-iconify 'suspend-emacs))
  4275. (setq viper-no-multiple-ESC t
  4276. viper-re-search t
  4277. viper-vi-style-in-minibuffer t
  4278. viper-search-wrap-around t
  4279. viper-electric-mode nil
  4280. viper-want-emacs-keys-in-vi nil
  4281. viper-want-emacs-keys-in-insert nil))
  4282. ((and (> viper-expert-level 1) (< viper-expert-level 5))
  4283. ;; intermediate to guru
  4284. (setq viper-no-multiple-ESC (if (viper-window-display-p)
  4285. t 'twice)
  4286. viper-electric-mode t
  4287. viper-want-emacs-keys-in-vi t
  4288. viper-want-emacs-keys-in-insert (> viper-expert-level 2))
  4289. (if (eq viper-expert-level 4) ; respect user's ex-style motion
  4290. ; and viper-no-multiple-ESC
  4291. (progn
  4292. (setq-default
  4293. viper-ex-style-editing
  4294. (viper-standard-value 'viper-ex-style-editing)
  4295. viper-ex-style-motion
  4296. (viper-standard-value 'viper-ex-style-motion))
  4297. (setq viper-ex-style-motion
  4298. (viper-standard-value 'viper-ex-style-motion)
  4299. viper-ex-style-editing
  4300. (viper-standard-value 'viper-ex-style-editing)
  4301. viper-re-search
  4302. (viper-standard-value 'viper-re-search)
  4303. viper-no-multiple-ESC
  4304. (viper-standard-value 'viper-no-multiple-ESC)))))
  4305. ;; A wizard!!
  4306. ;; Ideally, if 5 is selected, a buffer should pop up to let the
  4307. ;; user toggle the values of variables.
  4308. (t (setq-default viper-ex-style-editing
  4309. (viper-standard-value 'viper-ex-style-editing)
  4310. viper-ex-style-motion
  4311. (viper-standard-value 'viper-ex-style-motion))
  4312. (setq viper-want-ctl-h-help
  4313. (viper-standard-value 'viper-want-ctl-h-help)
  4314. viper-always
  4315. (viper-standard-value 'viper-always)
  4316. viper-no-multiple-ESC
  4317. (viper-standard-value 'viper-no-multiple-ESC)
  4318. viper-ex-style-motion
  4319. (viper-standard-value 'viper-ex-style-motion)
  4320. viper-ex-style-editing
  4321. (viper-standard-value 'viper-ex-style-editing)
  4322. viper-re-search
  4323. (viper-standard-value 'viper-re-search)
  4324. viper-electric-mode
  4325. (viper-standard-value 'viper-electric-mode)
  4326. viper-want-emacs-keys-in-vi
  4327. (viper-standard-value 'viper-want-emacs-keys-in-vi)
  4328. viper-want-emacs-keys-in-insert
  4329. (viper-standard-value 'viper-want-emacs-keys-in-insert))))
  4330. (viper-set-mode-vars-for viper-current-state)
  4331. (if (or viper-always
  4332. (and (> viper-expert-level 0) (> 5 viper-expert-level)))
  4333. (viper-set-hooks)))
  4334. ;; Ask user expert level.
  4335. (defun viper-ask-level (dont-change-unless)
  4336. (let ((ask-buffer " *viper-ask-level*")
  4337. level-changed repeated)
  4338. (save-window-excursion
  4339. (switch-to-buffer ask-buffer)
  4340. (while (or (> viper-expert-level viper-max-expert-level)
  4341. (< viper-expert-level 1)
  4342. (null dont-change-unless))
  4343. (erase-buffer)
  4344. (if repeated
  4345. (progn
  4346. (message "Invalid user level")
  4347. (beep 1))
  4348. (setq repeated t))
  4349. (setq dont-change-unless t
  4350. level-changed t)
  4351. (insert "
  4352. Please specify your level of familiarity with the venomous VI PERil
  4353. \(and the VI Plan for Emacs Rescue).
  4354. You can change it at any time by typing `M-x viper-set-expert-level RET'
  4355. 1 -- BEGINNER: Almost all Emacs features are suppressed.
  4356. Feels almost like straight Vi. File name completion and
  4357. command history in the minibuffer are thrown in as a bonus.
  4358. To use Emacs productively, you must reach level 3 or higher.
  4359. 2 -- MASTER: C-c now has its standard Emacs meaning in Vi command state,
  4360. so most Emacs commands can be used when Viper is in Vi state.
  4361. Good progress---you are well on the way to level 3!
  4362. 3 -- GRAND MASTER: Like 2, but most Emacs commands are available also
  4363. in Viper's insert state.
  4364. 4 -- GURU: Like 3, but user settings are respected for viper-no-multiple-ESC,
  4365. viper-ex-style-motion, viper-ex-style-editing, and
  4366. viper-re-search variables. Adjust these settings to your taste.
  4367. 5 -- WIZARD: Like 4, but user settings are also respected for viper-always,
  4368. viper-electric-mode, viper-want-ctl-h-help, viper-want-emacs-keys-in-vi,
  4369. and viper-want-emacs-keys-in-insert. Adjust these to your taste.
  4370. Please, specify your level now: ")
  4371. (setq viper-expert-level (- (viper-read-char-exclusive) ?0))
  4372. ) ; end while
  4373. ;; tell the user if level was changed
  4374. (and level-changed
  4375. (progn
  4376. (insert
  4377. (format "\n\n\n\n\n\t\tYou have selected user level %d"
  4378. viper-expert-level))
  4379. (if (y-or-n-p "Do you wish to make this change permanent? ")
  4380. ;; save the setting for viper-expert-level
  4381. (viper-save-setting
  4382. 'viper-expert-level
  4383. (format "Saving user level %d ..." viper-expert-level)
  4384. viper-custom-file-name))
  4385. ))
  4386. (bury-buffer) ; remove ask-buffer from screen
  4387. (message "")
  4388. )))
  4389. (defun viper-nil ()
  4390. (interactive)
  4391. (beep 1))
  4392. ;; if ENFORCE-BUFFER is not nil, error if CHAR is a marker in another buffer
  4393. (defun viper-register-to-point (char &optional enforce-buffer)
  4394. "Like `jump-to-register', but switches to another buffer in another window."
  4395. (interactive "cViper register to point: ")
  4396. (let ((val (get-register char)))
  4397. (cond
  4398. ((and (fboundp 'frame-configuration-p)
  4399. (frame-configuration-p val))
  4400. (set-frame-configuration val))
  4401. ((window-configuration-p val)
  4402. (set-window-configuration val))
  4403. ((viper-valid-marker val)
  4404. (if (and enforce-buffer
  4405. (not (equal (current-buffer) (marker-buffer val))))
  4406. (error (concat viper-EmptyTextmarker " in this buffer")
  4407. (viper-int-to-char (1- (+ char ?a)))))
  4408. (pop-to-buffer (marker-buffer val))
  4409. (goto-char val))
  4410. ((and (consp val) (eq (car val) 'file))
  4411. (find-file (cdr val)))
  4412. (t
  4413. (error viper-EmptyTextmarker (viper-int-to-char (1- (+ char ?a))))))))
  4414. (defun viper-save-kill-buffer ()
  4415. "Save then kill current buffer."
  4416. (interactive)
  4417. (if (< viper-expert-level 2)
  4418. (save-buffers-kill-emacs)
  4419. (save-buffer)
  4420. (kill-buffer (current-buffer))))
  4421. ;;; Bug Report
  4422. (defun viper-submit-report ()
  4423. "Submit bug report on Viper."
  4424. (interactive)
  4425. (let ((reporter-prompt-for-summary-p t)
  4426. (viper-device-type (viper-device-type))
  4427. color-display-p frame-parameters
  4428. minibuffer-emacs-face minibuffer-vi-face minibuffer-insert-face
  4429. varlist salutation window-config)
  4430. ;; If mode info is needed, add variable to `let' and then set it below,
  4431. ;; like we did with color-display-p.
  4432. (setq color-display-p (if (viper-window-display-p)
  4433. (viper-color-display-p)
  4434. 'non-x)
  4435. minibuffer-vi-face (if (viper-has-face-support-p)
  4436. (viper-get-face viper-minibuffer-vi-face)
  4437. 'non-x)
  4438. minibuffer-insert-face (if (viper-has-face-support-p)
  4439. (viper-get-face
  4440. viper-minibuffer-insert-face)
  4441. 'non-x)
  4442. minibuffer-emacs-face (if (viper-has-face-support-p)
  4443. (viper-get-face
  4444. viper-minibuffer-emacs-face)
  4445. 'non-x)
  4446. frame-parameters (if (fboundp 'frame-parameters)
  4447. (frame-parameters (selected-frame))))
  4448. (setq varlist (list 'viper-vi-minibuffer-minor-mode
  4449. 'viper-insert-minibuffer-minor-mode
  4450. 'viper-vi-intercept-minor-mode
  4451. 'viper-vi-local-user-minor-mode
  4452. 'viper-vi-kbd-minor-mode
  4453. 'viper-vi-global-user-minor-mode
  4454. 'viper-vi-state-modifier-minor-mode
  4455. 'viper-vi-diehard-minor-mode
  4456. 'viper-vi-basic-minor-mode
  4457. 'viper-replace-minor-mode
  4458. 'viper-insert-intercept-minor-mode
  4459. 'viper-insert-local-user-minor-mode
  4460. 'viper-insert-kbd-minor-mode
  4461. 'viper-insert-global-user-minor-mode
  4462. 'viper-insert-state-modifier-minor-mode
  4463. 'viper-insert-diehard-minor-mode
  4464. 'viper-insert-basic-minor-mode
  4465. 'viper-emacs-intercept-minor-mode
  4466. 'viper-emacs-local-user-minor-mode
  4467. 'viper-emacs-kbd-minor-mode
  4468. 'viper-emacs-global-user-minor-mode
  4469. 'viper-emacs-state-modifier-minor-mode
  4470. 'viper-automatic-iso-accents
  4471. 'viper-special-input-method
  4472. 'viper-want-emacs-keys-in-insert
  4473. 'viper-want-emacs-keys-in-vi
  4474. 'viper-keep-point-on-undo
  4475. 'viper-no-multiple-ESC
  4476. 'viper-electric-mode
  4477. 'viper-ESC-key
  4478. 'viper-want-ctl-h-help
  4479. 'viper-ex-style-editing
  4480. 'viper-delete-backwards-in-replace
  4481. 'viper-vi-style-in-minibuffer
  4482. 'viper-vi-state-hook
  4483. 'viper-insert-state-hook
  4484. 'viper-replace-state-hook
  4485. 'viper-emacs-state-hook
  4486. 'ex-cycle-other-window
  4487. 'ex-cycle-through-non-files
  4488. 'viper-expert-level
  4489. 'major-mode
  4490. 'viper-device-type
  4491. 'color-display-p
  4492. 'frame-parameters
  4493. 'minibuffer-vi-face
  4494. 'minibuffer-insert-face
  4495. 'minibuffer-emacs-face
  4496. ))
  4497. (setq salutation "
  4498. Congratulations! You may have unearthed a bug in Viper!
  4499. Please mail a concise, accurate summary of the problem to the address above.
  4500. -------------------------------------------------------------------")
  4501. (setq window-config (current-window-configuration))
  4502. (with-output-to-temp-buffer " *viper-info*"
  4503. (switch-to-buffer " *viper-info*")
  4504. (delete-other-windows)
  4505. (princ "
  4506. PLEASE FOLLOW THESE PROCEDURES
  4507. ------------------------------
  4508. Before reporting a bug, please verify that it is related to Viper, and is
  4509. not caused by other packages you are using.
  4510. Don't report compilation warnings, unless you are certain that there is a
  4511. problem. These warnings are normal and unavoidable.
  4512. Please note that users should not modify variables and keymaps other than
  4513. those advertised in the manual. Such `customization' is likely to crash
  4514. Viper, as it would any other improperly customized Emacs package.
  4515. If you are reporting an error message received while executing one of the
  4516. Viper commands, type:
  4517. M-x set-variable <Return> debug-on-error <Return> t <Return>
  4518. Then reproduce the error. The above command will cause Emacs to produce a
  4519. back trace of the execution that leads to the error. Please include this
  4520. trace in your bug report.
  4521. If you believe that one of Viper's commands goes into an infinite loop
  4522. \(e.g., Emacs freezes\), type:
  4523. M-x set-variable <Return> debug-on-quit <Return> t <Return>
  4524. Then reproduce the problem. Wait for a few seconds, then type C-g to abort
  4525. the current command. Include the resulting back trace in the bug report.
  4526. Mail anyway (y or n)? ")
  4527. (if (y-or-n-p "Mail anyway? ")
  4528. ()
  4529. (set-window-configuration window-config)
  4530. (error "Bug report aborted")))
  4531. (require 'reporter)
  4532. (set-window-configuration window-config)
  4533. (reporter-submit-bug-report "kifer@cs.stonybrook.edu"
  4534. (viper-version)
  4535. varlist
  4536. nil 'delete-other-windows
  4537. salutation)
  4538. ))
  4539. ;;; viper-cmd.el ends here