viper-cmd.el 170 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011
  1. ;;; viper-cmd.el --- Vi command support for Viper
  2. ;; Copyright (C) 1997-2015 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. ;; Listen to ESC key.
  868. (defun viper-intercept-ESC-key ()
  869. "Function that implements ESC key in Viper emulation of Vi."
  870. (interactive)
  871. ;; `key-binding' needs to be called in a context where Viper's
  872. ;; minor-mode map(s) have been temporarily disabled so the ESC
  873. ;; binding to viper-intercept-ESC-key doesn't hide the binding we're
  874. ;; looking for (Bug#9146):
  875. (let* ((cmd 'viper-intercept-ESC-key))
  876. ;; call the actual function to execute ESC (if no other symbols followed)
  877. ;; or the key bound to the ESC sequence (if the sequence was issued
  878. ;; with very short delay between characters).
  879. (if (eq cmd 'viper-intercept-ESC-key)
  880. (setq cmd
  881. (cond ((eq viper-current-state 'vi-state)
  882. 'viper-ESC)
  883. ((eq viper-current-state 'insert-state)
  884. 'viper-exit-insert-state)
  885. ((eq viper-current-state 'replace-state)
  886. 'viper-replace-state-exit-cmd)
  887. (t 'viper-change-state-to-vi)
  888. )))
  889. (call-interactively cmd)))
  890. ;; prefix argument for Vi mode
  891. ;; In Vi mode, prefix argument is a dotted pair (NUM . COM) where NUM
  892. ;; represents the numeric value of the prefix argument and COM represents
  893. ;; command prefix such as "c", "d", "m" and "y".
  894. ;; Get value part of prefix-argument ARG.
  895. (defsubst viper-p-val (arg)
  896. (cond ((null arg) 1)
  897. ((consp arg)
  898. (if (or (null (car arg)) (equal (car arg) '(nil)))
  899. 1 (car arg)))
  900. (t arg)))
  901. ;; Get raw value part of prefix-argument ARG.
  902. (defsubst viper-P-val (arg)
  903. (cond ((consp arg) (car arg))
  904. (t arg)))
  905. ;; Get com part of prefix-argument ARG.
  906. (defsubst viper-getcom (arg)
  907. (cond ((null arg) nil)
  908. ((consp arg) (cdr arg))
  909. (t nil)))
  910. ;; Get com part of prefix-argument ARG and modify it.
  911. (defun viper-getCom (arg)
  912. (let ((com (viper-getcom arg)))
  913. (cond ((viper= com ?c) ?c)
  914. ;; Previously, ?c was being converted to ?C, but this prevented
  915. ;; multiline replace regions.
  916. ;;((viper= com ?c) ?C)
  917. ((viper= com ?d) ?D)
  918. ((viper= com ?y) ?Y)
  919. (t com))))
  920. ;; Compute numeric prefix arg value.
  921. ;; Invoked by EVENT-CHAR. COM is the command part obtained so far.
  922. (defun viper-prefix-arg-value (event-char com)
  923. (let ((viper-intermediate-command 'viper-digit-argument)
  924. value func)
  925. ;; read while number
  926. (while (and (viper-characterp event-char)
  927. (>= event-char ?0) (<= event-char ?9))
  928. (setq value (+ (* (if (integerp value) value 0) 10) (- event-char ?0)))
  929. (setq event-char (viper-read-event-convert-to-char)))
  930. (setq prefix-arg value)
  931. (if com (setq prefix-arg (cons prefix-arg com)))
  932. (while (eq event-char ?U)
  933. (viper-describe-arg prefix-arg)
  934. (setq event-char (viper-read-event-convert-to-char)))
  935. (if (or com (and (not (eq viper-current-state 'vi-state))
  936. ;; make sure it is a Vi command
  937. (viper-characterp event-char)
  938. (viper-vi-command-p event-char)
  939. ))
  940. ;; If appears to be one of the vi commands,
  941. ;; then execute it with funcall and clear prefix-arg in order to not
  942. ;; confuse subsequent commands
  943. (progn
  944. ;; last-command-event is the char we want emacs to think was typed
  945. ;; last. If com is not nil, the viper-digit-argument command was
  946. ;; called from within viper-prefix-arg command, such as `d', `w',
  947. ;; etc., i.e., the user typed, say, d2. In this case, `com' would be
  948. ;; `d', `w', etc. If viper-digit-argument was invoked by
  949. ;; viper-escape-to-vi (which is indicated by the fact that the
  950. ;; current state is not vi-state), then `event-char' represents the
  951. ;; vi command to be executed (e.g., `d', `w', etc). Again,
  952. ;; last-command-event must make emacs believe that this is the command
  953. ;; we typed.
  954. (cond ((eq event-char 'return) (setq event-char ?\C-m))
  955. ((eq event-char 'delete) (setq event-char ?\C-?))
  956. ((eq event-char 'backspace) (setq event-char ?\C-h))
  957. ((eq event-char 'space) (setq event-char ?\ )))
  958. (setq last-command-event
  959. (if (featurep 'xemacs)
  960. (character-to-event (or com event-char))
  961. (or com event-char)))
  962. (setq func (viper-exec-form-in-vi
  963. `(key-binding (char-to-string ,event-char))))
  964. (funcall func prefix-arg)
  965. (setq prefix-arg nil))
  966. ;; some other command -- let emacs do it in its own way
  967. (viper-set-unread-command-events event-char))
  968. ))
  969. ;; Vi operator as prefix argument."
  970. (defun viper-prefix-arg-com (char value com)
  971. (let ((cont t)
  972. cmd-info
  973. cmd-to-exec-at-end)
  974. (while (and cont
  975. (viper-memq-char char
  976. (list ?c ?d ?y ?! ?< ?> ?= ?# ?r ?R ?\"
  977. viper-buffer-search-char)))
  978. (if com
  979. ;; this means that we already have a command character, so we
  980. ;; construct a com list and exit while. however, if char is "
  981. ;; it is an error.
  982. (progn
  983. ;; new com is (CHAR . OLDCOM)
  984. (if (viper-memq-char char '(?# ?\")) (error "Viper bell"))
  985. (setq com (cons char com))
  986. (setq cont nil))
  987. ;; If com is nil we set com as char, and read more. Again, if char is
  988. ;; ", we read the name of register and store it in viper-use-register.
  989. ;; if char is !, =, or #, a complete com is formed so we exit the while
  990. ;; loop.
  991. (cond ((viper-memq-char char '(?! ?=))
  992. (setq com char)
  993. (setq char (read-char))
  994. (setq cont nil))
  995. ((viper= char ?#)
  996. ;; read a char and encode it as com
  997. (setq com (+ 128 (read-char)))
  998. (setq char (read-char)))
  999. ((viper= char ?\")
  1000. (let ((reg (read-char)))
  1001. (if (viper-valid-register reg)
  1002. (setq viper-use-register reg)
  1003. (error "Viper bell"))
  1004. (setq char (read-char))))
  1005. (t
  1006. (setq com char)
  1007. (setq char (read-char))))))
  1008. (if (atom com)
  1009. ;; `com' is a single char, so we construct the command argument
  1010. ;; and if `char' is `?', we describe the arg; otherwise
  1011. ;; we prepare the command that will be executed at the end.
  1012. (progn
  1013. (setq cmd-info (cons value com))
  1014. (while (viper= char ?U)
  1015. (viper-describe-arg cmd-info)
  1016. (setq char (read-char)))
  1017. ;; `char' is a movement cmd, a digit arg cmd, or a register cmd---so
  1018. ;; we execute it at the very end
  1019. (or (viper-movement-command-p char)
  1020. (viper-digit-command-p char)
  1021. (viper-regsuffix-command-p char)
  1022. (viper= char ?!) ; bang command
  1023. (viper= char ?g) ; the gg command (like G0)
  1024. (error "Viper bell"))
  1025. (setq cmd-to-exec-at-end
  1026. (viper-exec-form-in-vi
  1027. `(key-binding (char-to-string ,char)))))
  1028. ;; as com is non-nil, this means that we have a command to execute
  1029. (if (viper-memq-char (car com) '(?r ?R))
  1030. ;; execute appropriate region command.
  1031. (let ((char (car com)) (com (cdr com)))
  1032. (setq prefix-arg (cons value com))
  1033. (if (viper= char ?r)
  1034. (viper-region prefix-arg)
  1035. (viper-Region prefix-arg))
  1036. ;; reset prefix-arg
  1037. (setq prefix-arg nil))
  1038. ;; otherwise, reset prefix arg and call appropriate command
  1039. (setq value (if (null value) 1 value))
  1040. (setq prefix-arg nil)
  1041. (cond
  1042. ;; If we change ?C to ?c here, then cc will enter replacement mode
  1043. ;; rather than deleting lines. However, it will affect 1 less line
  1044. ;; than normal. We decided to not use replacement mode here and
  1045. ;; follow Vi, since replacement mode on n full lines can be achieved
  1046. ;; with nC.
  1047. ((equal com '(?c . ?c)) (viper-line (cons value ?C)))
  1048. ((equal com '(?d . ?d)) (viper-line (cons value ?D)))
  1049. ((equal com '(?d . ?y)) (viper-yank-defun))
  1050. ((equal com '(?y . ?y)) (viper-line (cons value ?Y)))
  1051. ((equal com '(?< . ?<)) (viper-line (cons value ?<)))
  1052. ((equal com '(?> . ?>)) (viper-line (cons value ?>)))
  1053. ((equal com '(?! . ?!)) (viper-line (cons value ?!)))
  1054. ((equal com '(?= . ?=)) (viper-line (cons value ?=)))
  1055. ;; gg acts as G0
  1056. ((equal (car com) ?g) (viper-goto-line 0))
  1057. (t (error "Viper bell")))))
  1058. (if cmd-to-exec-at-end
  1059. (progn
  1060. (setq last-command-event
  1061. (viper-copy-event
  1062. (if (featurep 'xemacs) (character-to-event char) char)))
  1063. (condition-case err
  1064. (funcall cmd-to-exec-at-end cmd-info)
  1065. (error
  1066. (error "%s" (error-message-string err))))))
  1067. ))
  1068. (defun viper-describe-arg (arg)
  1069. (let (val com)
  1070. (setq val (viper-P-val arg)
  1071. com (viper-getcom arg))
  1072. (if (null val)
  1073. (if (null com)
  1074. (message "Value is nil, and command is nil")
  1075. (message "Value is nil, and command is `%c'" com))
  1076. (if (null com)
  1077. (message "Value is `%d', and command is nil" val)
  1078. (message "Value is `%d', and command is `%c'" val com)))))
  1079. (defun viper-digit-argument (arg)
  1080. "Begin numeric argument for the next command."
  1081. (interactive "P")
  1082. (viper-leave-region-active)
  1083. (viper-prefix-arg-value
  1084. (viper-last-command-char) (if (consp arg) (cdr arg) nil)))
  1085. (defun viper-command-argument (arg)
  1086. "Accept a motion command as an argument."
  1087. (interactive "P")
  1088. (let ((viper-intermediate-command 'viper-command-argument))
  1089. (condition-case nil
  1090. (viper-prefix-arg-com
  1091. (viper-last-command-char)
  1092. (cond ((null arg) nil)
  1093. ((consp arg) (car arg))
  1094. ((integerp arg) arg)
  1095. (t (error viper-InvalidCommandArgument)))
  1096. (cond ((null arg) nil)
  1097. ((consp arg) (cdr arg))
  1098. ((integerp arg) nil)
  1099. (t (error viper-InvalidCommandArgument))))
  1100. (quit (setq viper-use-register nil)
  1101. (signal 'quit nil)))
  1102. (viper-deactivate-mark)))
  1103. ;; repeat last destructive command
  1104. ;; Append region to text in register REG.
  1105. ;; START and END are buffer positions indicating what to append.
  1106. (defsubst viper-append-to-register (reg start end)
  1107. (set-register reg (concat (if (stringp (get-register reg))
  1108. (get-register reg) "")
  1109. (buffer-substring start end))))
  1110. ;; Saves last inserted text for possible use by viper-repeat command.
  1111. (defun viper-save-last-insertion (beg end)
  1112. (condition-case nil
  1113. (setq viper-last-insertion (buffer-substring beg end))
  1114. (error
  1115. ;; beg or end marker are somehow screwed up
  1116. (setq viper-last-insertion nil)))
  1117. (setq viper-last-insertion (buffer-substring beg end))
  1118. (or (< (length viper-d-com) 5)
  1119. (setcar (nthcdr 4 viper-d-com) viper-last-insertion))
  1120. (or (null viper-command-ring)
  1121. (ring-empty-p viper-command-ring)
  1122. (progn
  1123. (setcar (nthcdr 4 (viper-current-ring-item viper-command-ring))
  1124. viper-last-insertion)
  1125. ;; del most recent elt, if identical to the second most-recent
  1126. (viper-cleanup-ring viper-command-ring)))
  1127. )
  1128. (defsubst viper-yank-last-insertion ()
  1129. "Inserts the text saved by the previous viper-save-last-insertion command."
  1130. (condition-case nil
  1131. (insert viper-last-insertion)
  1132. (error nil)))
  1133. ;; define functions to be executed
  1134. ;; invoked by the `C' command
  1135. (defun viper-exec-change (m-com com)
  1136. (or (and (markerp viper-com-point) (marker-position viper-com-point))
  1137. (set-marker viper-com-point (point) (current-buffer)))
  1138. ;; handle C cmd at the eol and at eob.
  1139. (if (or (and (eolp) (= viper-com-point (point)))
  1140. (= viper-com-point (point-max)))
  1141. (progn
  1142. (insert " ")(backward-char 1)))
  1143. (if (= viper-com-point (point))
  1144. (viper-forward-char-carefully))
  1145. (push-mark viper-com-point)
  1146. (if (eq m-com 'viper-next-line-at-bol)
  1147. (viper-enlarge-region (mark t) (point)))
  1148. (if (< (point) (mark t))
  1149. (exchange-point-and-mark))
  1150. (if (eq (preceding-char) ?\n)
  1151. (viper-backward-char-carefully)) ; give back the newline
  1152. (if (eq viper-intermediate-command 'viper-repeat)
  1153. (viper-change-subr (mark t) (point))
  1154. (viper-change (mark t) (point))))
  1155. ;; this is invoked by viper-substitute-line
  1156. (defun viper-exec-Change (m-com com)
  1157. (save-excursion
  1158. (set-mark viper-com-point)
  1159. (viper-enlarge-region (mark t) (point))
  1160. (if viper-use-register
  1161. (progn
  1162. (cond ((viper-valid-register viper-use-register '(letter digit))
  1163. (copy-to-register
  1164. viper-use-register (mark t) (point) nil))
  1165. ((viper-valid-register viper-use-register '(Letter))
  1166. (viper-append-to-register
  1167. (downcase viper-use-register) (mark t) (point)))
  1168. (t (setq viper-use-register nil)
  1169. (error viper-InvalidRegister viper-use-register)))
  1170. (setq viper-use-register nil)))
  1171. (delete-region (mark t) (point)))
  1172. (open-line 1)
  1173. (if (eq viper-intermediate-command 'viper-repeat)
  1174. (viper-yank-last-insertion)
  1175. (viper-change-state-to-insert)
  1176. ))
  1177. (defun viper-exec-delete (m-com com)
  1178. (or (and (markerp viper-com-point) (marker-position viper-com-point))
  1179. (set-marker viper-com-point (point) (current-buffer)))
  1180. (let (chars-deleted)
  1181. (if viper-use-register
  1182. (progn
  1183. (cond ((viper-valid-register viper-use-register '(letter digit))
  1184. (copy-to-register
  1185. viper-use-register viper-com-point (point) nil))
  1186. ((viper-valid-register viper-use-register '(Letter))
  1187. (viper-append-to-register
  1188. (downcase viper-use-register) viper-com-point (point)))
  1189. (t (setq viper-use-register nil)
  1190. (error viper-InvalidRegister viper-use-register)))
  1191. (setq viper-use-register nil)))
  1192. (setq last-command
  1193. (if (eq last-command 'd-command) 'kill-region nil))
  1194. (setq chars-deleted (abs (- (point) viper-com-point)))
  1195. (if (> chars-deleted viper-change-notification-threshold)
  1196. (unless (viper-is-in-minibuffer)
  1197. (message "Deleted %d characters" chars-deleted)))
  1198. (kill-region viper-com-point (point))
  1199. (setq this-command 'd-command)
  1200. (if viper-ex-style-motion
  1201. (if (and (eolp) (not (bolp))) (backward-char 1)))))
  1202. (defun viper-exec-Delete (m-com com)
  1203. (save-excursion
  1204. (set-mark viper-com-point)
  1205. (viper-enlarge-region (mark t) (point))
  1206. (let (lines-deleted)
  1207. (if viper-use-register
  1208. (progn
  1209. (cond ((viper-valid-register viper-use-register '(letter digit))
  1210. (copy-to-register
  1211. viper-use-register (mark t) (point) nil))
  1212. ((viper-valid-register viper-use-register '(Letter))
  1213. (viper-append-to-register
  1214. (downcase viper-use-register) (mark t) (point)))
  1215. (t (setq viper-use-register nil)
  1216. (error viper-InvalidRegister viper-use-register)))
  1217. (setq viper-use-register nil)))
  1218. (setq last-command
  1219. (if (eq last-command 'D-command) 'kill-region nil))
  1220. (setq lines-deleted (count-lines (point) viper-com-point))
  1221. (if (> lines-deleted viper-change-notification-threshold)
  1222. (unless (viper-is-in-minibuffer)
  1223. (message "Deleted %d lines" lines-deleted)))
  1224. (kill-region (mark t) (point))
  1225. (if (eq m-com 'viper-line) (setq this-command 'D-command)))
  1226. (back-to-indentation)))
  1227. ;; save region
  1228. (defun viper-exec-yank (m-com com)
  1229. (or (and (markerp viper-com-point) (marker-position viper-com-point))
  1230. (set-marker viper-com-point (point) (current-buffer)))
  1231. (let (chars-saved)
  1232. (if viper-use-register
  1233. (progn
  1234. (cond ((viper-valid-register viper-use-register '(letter digit))
  1235. (copy-to-register
  1236. viper-use-register viper-com-point (point) nil))
  1237. ((viper-valid-register viper-use-register '(Letter))
  1238. (viper-append-to-register
  1239. (downcase viper-use-register) viper-com-point (point)))
  1240. (t (setq viper-use-register nil)
  1241. (error viper-InvalidRegister viper-use-register)))
  1242. (setq viper-use-register nil)))
  1243. (setq last-command nil)
  1244. (copy-region-as-kill viper-com-point (point))
  1245. (setq chars-saved (abs (- (point) viper-com-point)))
  1246. (if (> chars-saved viper-change-notification-threshold)
  1247. (unless (viper-is-in-minibuffer)
  1248. (message "Saved %d characters" chars-saved)))
  1249. (goto-char viper-com-point)))
  1250. ;; save lines
  1251. (defun viper-exec-Yank (m-com com)
  1252. (save-excursion
  1253. (set-mark viper-com-point)
  1254. (viper-enlarge-region (mark t) (point))
  1255. (let (lines-saved)
  1256. (if viper-use-register
  1257. (progn
  1258. (cond ((viper-valid-register viper-use-register '(letter digit))
  1259. (copy-to-register
  1260. viper-use-register (mark t) (point) nil))
  1261. ((viper-valid-register viper-use-register '(Letter))
  1262. (viper-append-to-register
  1263. (downcase viper-use-register) (mark t) (point)))
  1264. (t (setq viper-use-register nil)
  1265. (error viper-InvalidRegister viper-use-register)))
  1266. (setq viper-use-register nil)))
  1267. (setq last-command nil)
  1268. (copy-region-as-kill (mark t) (point))
  1269. (setq lines-saved (count-lines (mark t) (point)))
  1270. (if (> lines-saved viper-change-notification-threshold)
  1271. (unless (viper-is-in-minibuffer)
  1272. (message "Saved %d lines" lines-saved)))))
  1273. (viper-deactivate-mark)
  1274. (goto-char viper-com-point))
  1275. (defun viper-exec-bang (m-com com)
  1276. (save-excursion
  1277. (set-mark viper-com-point)
  1278. (viper-enlarge-region (mark t) (point))
  1279. (exchange-point-and-mark)
  1280. (shell-command-on-region
  1281. (mark t) (point)
  1282. (if (viper= com ?!)
  1283. (setq viper-last-shell-com
  1284. (viper-read-string-with-history
  1285. "!"
  1286. nil
  1287. 'viper-shell-history
  1288. (car viper-shell-history)
  1289. ))
  1290. viper-last-shell-com)
  1291. t t)))
  1292. (defun viper-exec-equals (m-com com)
  1293. (save-excursion
  1294. (set-mark viper-com-point)
  1295. (viper-enlarge-region (mark t) (point))
  1296. (if (> (mark t) (point)) (exchange-point-and-mark))
  1297. (indent-region (mark t) (point) nil)))
  1298. (defun viper-exec-shift (m-com com)
  1299. (save-excursion
  1300. (set-mark viper-com-point)
  1301. (viper-enlarge-region (mark t) (point))
  1302. (if (> (mark t) (point)) (exchange-point-and-mark))
  1303. (indent-rigidly (mark t) (point)
  1304. (if (viper= com ?>)
  1305. viper-shift-width
  1306. (- viper-shift-width))))
  1307. ;; return point to where it was before shift
  1308. (goto-char viper-com-point))
  1309. ;; this is needed because some commands fake com by setting it to ?r, which
  1310. ;; denotes repeated insert command.
  1311. (defsubst viper-exec-dummy (m-com com)
  1312. nil)
  1313. (defun viper-exec-buffer-search (m-com com)
  1314. (setq viper-s-string
  1315. (regexp-quote (buffer-substring (point) viper-com-point)))
  1316. (setq viper-s-forward t)
  1317. (setq viper-search-history (cons viper-s-string viper-search-history))
  1318. (setq viper-intermediate-command 'viper-exec-buffer-search)
  1319. (viper-search viper-s-string viper-s-forward 1))
  1320. (defvar viper-exec-array (make-vector 128 nil))
  1321. ;; Using a dispatch array allows adding functions like buffer search
  1322. ;; without affecting other functions. Buffer search can now be bound
  1323. ;; to any character.
  1324. (aset viper-exec-array ?c 'viper-exec-change)
  1325. (aset viper-exec-array ?C 'viper-exec-Change)
  1326. (aset viper-exec-array ?d 'viper-exec-delete)
  1327. (aset viper-exec-array ?D 'viper-exec-Delete)
  1328. (aset viper-exec-array ?y 'viper-exec-yank)
  1329. (aset viper-exec-array ?Y 'viper-exec-Yank)
  1330. (aset viper-exec-array ?r 'viper-exec-dummy)
  1331. (aset viper-exec-array ?! 'viper-exec-bang)
  1332. (aset viper-exec-array ?< 'viper-exec-shift)
  1333. (aset viper-exec-array ?> 'viper-exec-shift)
  1334. (aset viper-exec-array ?= 'viper-exec-equals)
  1335. ;; This function is called by various movement commands to execute a
  1336. ;; destructive command on the region specified by the movement command. For
  1337. ;; instance, if the user types cw, then the command viper-forward-word will
  1338. ;; call viper-execute-com to execute viper-exec-change, which eventually will
  1339. ;; call viper-change to invoke the replace mode on the region.
  1340. ;;
  1341. ;; The var viper-d-com is set to (M-COM VAL COM REG INSERTED-TEXT COMMAND-KEYS)
  1342. ;; via a call to viper-set-destructive-command, for later use by viper-repeat.
  1343. (defun viper-execute-com (m-com val com)
  1344. (let ((reg viper-use-register))
  1345. ;; this is the special command `#'
  1346. (if (> com 128)
  1347. (viper-special-prefix-com (- com 128))
  1348. (let ((fn (aref viper-exec-array com)))
  1349. (if (null fn)
  1350. (error "%c: %s" com viper-InvalidViCommand)
  1351. (funcall fn m-com com))))
  1352. (if (viper-dotable-command-p com)
  1353. (viper-set-destructive-command
  1354. (list m-com val com reg nil nil)))
  1355. ))
  1356. (defun viper-repeat (arg)
  1357. "Re-execute last destructive command.
  1358. Use the info in viper-d-com, which has the form
  1359. \(com val ch reg inserted-text command-keys),
  1360. where `com' is the command to be re-executed, `val' is the
  1361. argument to `com', `ch' is a flag for repeat, and `reg' is optional;
  1362. if it exists, it is the name of the register for `com'.
  1363. If the prefix argument ARG is non-nil, it is used instead of `val'."
  1364. (interactive "P")
  1365. (let ((save-point (point)) ; save point before repeating prev cmd
  1366. ;; Pass along that we are repeating a destructive command
  1367. ;; This tells viper-set-destructive-command not to update
  1368. ;; viper-command-ring
  1369. (viper-intermediate-command 'viper-repeat))
  1370. (if (eq last-command 'viper-undo)
  1371. ;; if the last command was viper-undo, then undo-more
  1372. (viper-undo-more)
  1373. ;; otherwise execute the command stored in viper-d-com. if arg is
  1374. ;; non-nil its prefix value is used as new prefix value for the command.
  1375. (let ((m-com (car viper-d-com))
  1376. (val (viper-P-val arg))
  1377. (com (nth 2 viper-d-com))
  1378. (reg (nth 3 viper-d-com)))
  1379. (if (null val) (setq val (nth 1 viper-d-com)))
  1380. (if (null m-com) (error "No previous command to repeat"))
  1381. (setq viper-use-register reg)
  1382. (if (nth 4 viper-d-com) ; text inserted by command
  1383. (setq viper-last-insertion (nth 4 viper-d-com)
  1384. viper-d-char (nth 4 viper-d-com)))
  1385. (funcall m-com (cons val com))
  1386. (cond ((and (< save-point (point)) viper-keep-point-on-repeat)
  1387. (goto-char save-point)) ; go back to before repeat.
  1388. ((and (< save-point (point)) viper-ex-style-editing)
  1389. (or (bolp) (backward-char 1))))
  1390. (if (and (eolp) (not (bolp)))
  1391. (backward-char 1))
  1392. ))
  1393. (viper-adjust-undo) ; take care of undo
  1394. ;; If the prev cmd was rotating the command ring, this means that `.' has
  1395. ;; just executed a command from that ring. So, push it on the ring again.
  1396. ;; If we are just executing previous command , then don't push viper-d-com
  1397. ;; because viper-d-com is not fully constructed in this case (its keys and
  1398. ;; the inserted text may be nil). Besides, in this case, the command
  1399. ;; executed by `.' is already on the ring.
  1400. (if (eq last-command 'viper-display-current-destructive-command)
  1401. (viper-push-onto-ring viper-d-com 'viper-command-ring))
  1402. (viper-deactivate-mark)
  1403. ))
  1404. (defun viper-repeat-from-history ()
  1405. "Repeat a destructive command from history.
  1406. Doesn't change viper-command-ring in any way, so `.' will work as before
  1407. executing this command.
  1408. This command is supposed to be bound to a two-character Vi macro where
  1409. the second character is a digit 0 to 9. The digit indicates which
  1410. history command to execute. `<char>0' is equivalent to `.', `<char>1'
  1411. invokes the command before that, etc."
  1412. (interactive)
  1413. (let* ((viper-intermediate-command 'repeating-display-destructive-command)
  1414. (idx (cond (viper-this-kbd-macro
  1415. (string-to-number
  1416. (symbol-name (elt viper-this-kbd-macro 1))))
  1417. (t 0)))
  1418. (num idx)
  1419. (viper-d-com viper-d-com))
  1420. (or (and (numberp num) (<= 0 num) (<= num 9))
  1421. (progn
  1422. (setq idx 0
  1423. num 0)
  1424. (message
  1425. "`viper-repeat-from-history' must be invoked as a Vi macro bound to `<key><digit>'")))
  1426. (while (< 0 num)
  1427. (setq viper-d-com (viper-special-ring-rotate1 viper-command-ring -1))
  1428. (setq num (1- num)))
  1429. (viper-repeat nil)
  1430. (while (> idx num)
  1431. (viper-special-ring-rotate1 viper-command-ring 1)
  1432. (setq num (1+ num)))
  1433. ))
  1434. ;; The hash-command. It is invoked interactively by the key sequence #<char>.
  1435. ;; The chars that can follow `#' are determined by viper-hash-command-p
  1436. (defun viper-special-prefix-com (char)
  1437. (cond ((viper= char ?c)
  1438. (downcase-region (min viper-com-point (point))
  1439. (max viper-com-point (point))))
  1440. ((viper= char ?C)
  1441. (upcase-region (min viper-com-point (point))
  1442. (max viper-com-point (point))))
  1443. ((viper= char ?g)
  1444. (push-mark viper-com-point t)
  1445. ;; execute the last emacs kbd macro on each line of the region
  1446. (viper-global-execute))
  1447. ((viper= char ?q)
  1448. (push-mark viper-com-point t)
  1449. (viper-quote-region))
  1450. ((viper= char ?s)
  1451. (funcall viper-spell-function viper-com-point (point)))
  1452. (t (error "#%c: %s" char viper-InvalidViCommand))))
  1453. ;; undoing
  1454. ;; hook used inside undo
  1455. (defvar viper-undo-functions nil)
  1456. ;; Runs viper-before-change-functions inside before-change-functions
  1457. (defun viper-undo-sentinel (beg end length)
  1458. (run-hook-with-args 'viper-undo-functions beg end length))
  1459. (add-hook 'after-change-functions 'viper-undo-sentinel)
  1460. ;; Hook used in viper-undo
  1461. (defun viper-after-change-undo-hook (beg end len)
  1462. (if (and (boundp 'undo-in-progress) undo-in-progress)
  1463. (setq undo-beg-posn beg
  1464. undo-end-posn (or end beg))
  1465. ;; some other hooks may be changing various text properties in
  1466. ;; the buffer in response to 'undo'; so remove this hook to avoid
  1467. ;; its repeated invocation
  1468. (remove-hook 'viper-undo-functions 'viper-after-change-undo-hook 'local)
  1469. ))
  1470. (defun viper-undo ()
  1471. "Undo previous change."
  1472. (interactive)
  1473. (message "undo!")
  1474. (let ((modified (buffer-modified-p))
  1475. (before-undo-pt (point-marker))
  1476. undo-beg-posn undo-end-posn)
  1477. ;; the viper-after-change-undo-hook removes itself after the 1st invocation
  1478. (add-hook 'viper-undo-functions 'viper-after-change-undo-hook nil 'local)
  1479. (undo-start)
  1480. (undo-more 2)
  1481. ;;(setq undo-beg-posn (or undo-beg-posn (point))
  1482. ;; undo-end-posn (or undo-end-posn (point)))
  1483. ;;(setq undo-beg-posn (or undo-beg-posn before-undo-pt)
  1484. ;; undo-end-posn (or undo-end-posn undo-beg-posn))
  1485. (if (and undo-beg-posn undo-end-posn)
  1486. (progn
  1487. (goto-char undo-beg-posn)
  1488. (sit-for 0)
  1489. (if (and viper-keep-point-on-undo
  1490. (pos-visible-in-window-p before-undo-pt))
  1491. (progn
  1492. (push-mark (point-marker) t)
  1493. (viper-sit-for-short 300)
  1494. (goto-char undo-end-posn)
  1495. (viper-sit-for-short 300)
  1496. (if (pos-visible-in-window-p undo-beg-posn)
  1497. (goto-char before-undo-pt)
  1498. (goto-char undo-beg-posn)))
  1499. (push-mark before-undo-pt t))
  1500. ))
  1501. (if (and (eolp) (not (bolp))) (backward-char 1))
  1502. )
  1503. (setq this-command 'viper-undo))
  1504. ;; Continue undoing previous changes.
  1505. (defun viper-undo-more ()
  1506. (message "undo more!")
  1507. (condition-case nil
  1508. (undo-more 1)
  1509. (error (beep)
  1510. (message "No further undo information in this buffer")))
  1511. (if (and (eolp) (not (bolp))) (backward-char 1))
  1512. (setq this-command 'viper-undo))
  1513. ;; The following two functions are used to set up undo properly.
  1514. ;; In VI, unlike Emacs, if you open a line, say, and add a bunch of lines,
  1515. ;; they are undone all at once.
  1516. (defun viper-adjust-undo ()
  1517. (if viper-undo-needs-adjustment
  1518. (let ((inhibit-quit t)
  1519. tmp tmp2)
  1520. (setq viper-undo-needs-adjustment nil)
  1521. (if (listp buffer-undo-list)
  1522. (if (setq tmp (memq viper-buffer-undo-list-mark buffer-undo-list))
  1523. (progn
  1524. (setq tmp2 (cdr tmp)) ; the part after mark
  1525. ;; cut tail from buffer-undo-list temporarily by direct
  1526. ;; manipulation with pointers in buffer-undo-list
  1527. (setcdr tmp nil)
  1528. (setq buffer-undo-list (delq nil buffer-undo-list))
  1529. (setq buffer-undo-list
  1530. (delq viper-buffer-undo-list-mark buffer-undo-list))
  1531. ;; restore tail of buffer-undo-list
  1532. (setq buffer-undo-list (nconc buffer-undo-list tmp2)))
  1533. (setq buffer-undo-list (delq nil buffer-undo-list)))))
  1534. ))
  1535. (defun viper-set-complex-command-for-undo ()
  1536. (if (listp buffer-undo-list)
  1537. (if (not viper-undo-needs-adjustment)
  1538. (let ((inhibit-quit t))
  1539. (setq buffer-undo-list
  1540. (cons viper-buffer-undo-list-mark buffer-undo-list))
  1541. (setq viper-undo-needs-adjustment t)))))
  1542. ;;; Viper's destructive Command ring utilities
  1543. (defun viper-display-current-destructive-command ()
  1544. (let ((text (nth 4 viper-d-com))
  1545. (keys (nth 5 viper-d-com))
  1546. (max-text-len 30))
  1547. (setq this-command 'viper-display-current-destructive-command)
  1548. (message " `.' runs `%s'%s"
  1549. (viper-array-to-string keys)
  1550. (viper-abbreviate-string
  1551. (if (featurep 'xemacs)
  1552. (replace-in-string ; xemacs
  1553. (cond ((characterp text) (char-to-string text))
  1554. ((stringp text) text)
  1555. (t ""))
  1556. "\n" "^J")
  1557. text ; emacs
  1558. )
  1559. max-text-len
  1560. (format-message " inserting `") (format-message "'")
  1561. " ......."))
  1562. ))
  1563. ;; don't change viper-d-com if it was viper-repeat command invoked with `.'
  1564. ;; or in some other way (non-interactively).
  1565. (defun viper-set-destructive-command (list)
  1566. (or (eq viper-intermediate-command 'viper-repeat)
  1567. (progn
  1568. (setq viper-d-com list)
  1569. (setcar (nthcdr 5 viper-d-com)
  1570. (viper-array-to-string (if (arrayp viper-this-command-keys)
  1571. viper-this-command-keys
  1572. (this-command-keys))))
  1573. (viper-push-onto-ring viper-d-com 'viper-command-ring)))
  1574. (setq viper-this-command-keys nil))
  1575. (defun viper-prev-destructive-command (next)
  1576. "Find previous destructive command in the history of destructive commands.
  1577. With prefix argument, find next destructive command."
  1578. (interactive "P")
  1579. (let (cmd viper-intermediate-command)
  1580. (if (eq last-command 'viper-display-current-destructive-command)
  1581. ;; repeated search through command history
  1582. (setq viper-intermediate-command
  1583. 'repeating-display-destructive-command)
  1584. ;; first search through command history--set temp ring
  1585. (setq viper-temp-command-ring (ring-copy viper-command-ring)))
  1586. (setq cmd (if next
  1587. (viper-special-ring-rotate1 viper-temp-command-ring 1)
  1588. (viper-special-ring-rotate1 viper-temp-command-ring -1)))
  1589. (if (null cmd)
  1590. ()
  1591. (setq viper-d-com cmd))
  1592. (viper-display-current-destructive-command)))
  1593. (defun viper-next-destructive-command ()
  1594. "Find next destructive command in the history of destructive commands."
  1595. (interactive)
  1596. (viper-prev-destructive-command 'next))
  1597. (defun viper-insert-prev-from-insertion-ring (arg)
  1598. "Cycle through insertion ring in the direction of older insertions.
  1599. Undoes previous insertion and inserts new.
  1600. With prefix argument, cycles in the direction of newer elements.
  1601. In minibuffer, this command executes whatever the invocation key is bound
  1602. to in the global map, instead of cycling through the insertion ring."
  1603. (interactive "P")
  1604. (let (viper-intermediate-command)
  1605. (if (eq last-command 'viper-insert-from-insertion-ring)
  1606. (progn ; repeated search through insertion history
  1607. (setq viper-intermediate-command 'repeating-insertion-from-ring)
  1608. (if (eq viper-current-state 'replace-state)
  1609. (undo 1)
  1610. (if viper-last-inserted-string-from-insertion-ring
  1611. (backward-delete-char
  1612. (length viper-last-inserted-string-from-insertion-ring))))
  1613. )
  1614. ;;first search through insertion history
  1615. (setq viper-temp-insertion-ring (ring-copy viper-insertion-ring)))
  1616. (setq this-command 'viper-insert-from-insertion-ring)
  1617. ;; so that things will be undone properly
  1618. (setq buffer-undo-list (cons nil buffer-undo-list))
  1619. (setq viper-last-inserted-string-from-insertion-ring
  1620. (viper-special-ring-rotate1 viper-temp-insertion-ring (if arg 1 -1)))
  1621. ;; this change of viper-intermediate-command must come after
  1622. ;; viper-special-ring-rotate1, so that the ring will rotate, but before the
  1623. ;; insertion.
  1624. (setq viper-intermediate-command nil)
  1625. (if viper-last-inserted-string-from-insertion-ring
  1626. (insert viper-last-inserted-string-from-insertion-ring))
  1627. ))
  1628. (defun viper-insert-next-from-insertion-ring ()
  1629. "Cycle through insertion ring in the direction of older insertions.
  1630. Undo previous insertion and inserts new."
  1631. (interactive)
  1632. (viper-insert-prev-from-insertion-ring 'next))
  1633. ;; some region utilities
  1634. ;; If at the last line of buffer, add \\n before eob, if newline is missing.
  1635. (defun viper-add-newline-at-eob-if-necessary ()
  1636. (save-excursion
  1637. (end-of-line)
  1638. ;; make sure all lines end with newline, unless in the minibuffer or
  1639. ;; when requested otherwise (require-final-newline is nil)
  1640. (save-restriction
  1641. (widen)
  1642. (if (and (eobp)
  1643. (not (bolp))
  1644. require-final-newline
  1645. ;; add newline only if we actually edited buffer. otherwise it
  1646. ;; might unintentionally modify binary buffers
  1647. (buffer-modified-p)
  1648. (not (viper-is-in-minibuffer))
  1649. (not buffer-read-only))
  1650. ;; text property may be read-only
  1651. (condition-case nil
  1652. (insert "\n")
  1653. (error nil))
  1654. ))
  1655. ))
  1656. (defun viper-yank-defun ()
  1657. (mark-defun)
  1658. (copy-region-as-kill (point) (mark t)))
  1659. ;; Enlarge region between BEG and END.
  1660. (defun viper-enlarge-region (beg end)
  1661. (or beg (setq beg end)) ; if beg is nil, set to end
  1662. (or end (setq end beg)) ; if end is nil, set to beg
  1663. (if (< beg end)
  1664. (progn (goto-char beg) (set-mark end))
  1665. (goto-char end)
  1666. (set-mark beg))
  1667. (beginning-of-line)
  1668. (exchange-point-and-mark)
  1669. (if (or (not (eobp)) (not (bolp))) (forward-line 1))
  1670. (if (not (eobp)) (beginning-of-line))
  1671. (if (> beg end) (exchange-point-and-mark)))
  1672. ;; Quote region by each line with a user supplied string.
  1673. (defun viper-quote-region ()
  1674. (let ((quote-str viper-quote-string)
  1675. (do-not-change-default t))
  1676. (setq quote-str
  1677. (viper-read-string-with-history
  1678. "Quote string: "
  1679. nil
  1680. 'viper-quote-region-history
  1681. (cond ((string-match "tex.*-mode" (symbol-name major-mode)) "%%")
  1682. ((string-match "java.*-mode" (symbol-name major-mode)) "//")
  1683. ((string-match "perl.*-mode" (symbol-name major-mode)) "#")
  1684. ((string-match "lisp.*-mode" (symbol-name major-mode)) ";;")
  1685. ((memq major-mode '(c-mode cc-mode c++-mode)) "//")
  1686. ((memq major-mode '(sh-mode shell-mode)) "#")
  1687. (t (setq do-not-change-default nil)
  1688. quote-str))))
  1689. (or do-not-change-default
  1690. (setq viper-quote-string quote-str))
  1691. (viper-enlarge-region (point) (mark t))
  1692. (if (> (point) (mark t)) (exchange-point-and-mark))
  1693. (insert quote-str)
  1694. (beginning-of-line)
  1695. (forward-line 1)
  1696. (while (and (< (point) (mark t)) (bolp))
  1697. (insert quote-str)
  1698. (beginning-of-line)
  1699. (forward-line 1))))
  1700. ;; Tells whether BEG is on the same line as END.
  1701. ;; If one of the args is nil, it'll return nil.
  1702. (defun viper-same-line (beg end)
  1703. (let ((selective-display nil)
  1704. (incr 0)
  1705. temp)
  1706. (if (and beg end (> beg end))
  1707. (setq temp beg
  1708. beg end
  1709. end temp))
  1710. (if (and beg end)
  1711. (cond ((or (> beg (point-max)) (> end (point-max))) ; out of range
  1712. nil)
  1713. (t
  1714. ;; This 'if' is needed because Emacs treats the next empty line
  1715. ;; as part of the previous line.
  1716. (if (= (viper-line-pos 'start) end)
  1717. (setq incr 1))
  1718. (<= (+ incr (count-lines beg end)) 1))))
  1719. ))
  1720. ;; Check if the string ends with a newline.
  1721. (defun viper-end-with-a-newline-p (string)
  1722. (or (string= string "")
  1723. (= (viper-seq-last-elt string) ?\n)))
  1724. (defun viper-tmp-insert-at-eob (msg)
  1725. (let ((savemax (point-max)))
  1726. (goto-char savemax)
  1727. (insert msg)
  1728. (sit-for 2)
  1729. (goto-char savemax) (delete-region (point) (point-max))
  1730. ))
  1731. ;;; Minibuffer business
  1732. (defsubst viper-set-minibuffer-style ()
  1733. (add-hook 'minibuffer-setup-hook 'viper-minibuffer-setup-sentinel)
  1734. (add-hook 'post-command-hook 'viper-minibuffer-post-command-hook))
  1735. (defun viper-minibuffer-setup-sentinel ()
  1736. (let ((hook (if viper-vi-style-in-minibuffer
  1737. 'viper-change-state-to-insert
  1738. 'viper-change-state-to-emacs)))
  1739. ;; making buffer-local variables so that normal buffers won't affect the
  1740. ;; minibuffer and vice versa. Otherwise, command arguments will affect
  1741. ;; minibuffer ops and insertions from the minibuffer will change those in
  1742. ;; the normal buffers
  1743. (make-local-variable 'viper-d-com)
  1744. (make-local-variable 'viper-last-insertion)
  1745. (make-local-variable 'viper-command-ring)
  1746. (setq viper-d-com nil
  1747. viper-last-insertion nil
  1748. viper-command-ring nil)
  1749. (funcall hook)
  1750. ))
  1751. ;; This is a temp hook that uses free variables init-message and viper-initial.
  1752. ;; A dirty feature, but it is the simplest way to have it do the right thing.
  1753. ;; The INIT-MESSAGE and VIPER-INITIAL vars come from the scope set by
  1754. ;; viper-read-string-with-history
  1755. (defun viper-minibuffer-standard-hook ()
  1756. (if (stringp init-message)
  1757. (viper-tmp-insert-at-eob init-message))
  1758. (when (stringp viper-initial)
  1759. ;; don't wait if we have unread events or in kbd macro
  1760. (or unread-command-events
  1761. executing-kbd-macro
  1762. (sit-for 840))
  1763. (if (fboundp 'minibuffer-prompt-end)
  1764. (delete-region (minibuffer-prompt-end) (point-max))
  1765. (erase-buffer))
  1766. (insert viper-initial)))
  1767. (defsubst viper-minibuffer-real-start ()
  1768. (if (fboundp 'minibuffer-prompt-end)
  1769. (minibuffer-prompt-end)
  1770. (point-min)))
  1771. (defun viper-minibuffer-post-command-hook()
  1772. (when (active-minibuffer-window)
  1773. (when (< (point) (viper-minibuffer-real-start))
  1774. (goto-char (viper-minibuffer-real-start)))))
  1775. ;; Interpret last event in the local map first; if fails, use exit-minibuffer.
  1776. ;; Run viper-minibuffer-exit-hook before exiting.
  1777. (defun viper-exit-minibuffer ()
  1778. "Exit minibuffer Viper way."
  1779. (interactive)
  1780. (let (command)
  1781. (setq command (local-key-binding (char-to-string (viper-last-command-char))))
  1782. (run-hooks 'viper-minibuffer-exit-hook)
  1783. (if command
  1784. (command-execute command)
  1785. (exit-minibuffer))))
  1786. (defcustom viper-smart-suffix-list
  1787. '("" "tex" "c" "cc" "C" "java" "el" "html" "htm" "xml"
  1788. "pl" "flr" "P" "p" "h" "H")
  1789. "List of suffixes that Viper tries to append to filenames ending with a `.'.
  1790. This is useful when the current directory contains files with the same
  1791. prefix and many different suffixes. Usually, only one of the suffixes
  1792. represents an editable file. However, file completion will stop at the `.'
  1793. The smart suffix feature lets you hit RET in such a case, and Viper will
  1794. select the appropriate suffix.
  1795. Suffixes are tried in the order given and the first suffix for which a
  1796. corresponding file exists is selected. If no file exists for any of the
  1797. suffixes, the user is asked to confirm.
  1798. To turn this feature off, set this variable to nil."
  1799. :type '(repeat string)
  1800. :group 'viper-misc)
  1801. ;; Try to add a suitable suffix to files whose name ends with a `.'
  1802. ;; Useful when the user hits RET on a non-completed file name.
  1803. ;; Used as a minibuffer exit hook in read-file-name
  1804. (defun viper-file-add-suffix ()
  1805. (let ((count 0)
  1806. (len (length viper-smart-suffix-list))
  1807. (file (buffer-substring-no-properties
  1808. (viper-minibuffer-real-start) (point-max)))
  1809. found key cmd suff)
  1810. (goto-char (point-max))
  1811. (if (and viper-smart-suffix-list (string-match "\\.$" file))
  1812. (progn
  1813. (while (and (not found) (< count len))
  1814. (setq suff (nth count viper-smart-suffix-list)
  1815. count (1+ count))
  1816. (if (file-exists-p
  1817. (format "%s%s" (substitute-in-file-name file) suff))
  1818. (progn
  1819. (setq found t)
  1820. (insert suff))))
  1821. (if found
  1822. ()
  1823. (viper-tmp-insert-at-eob " [Please complete file name]")
  1824. (unwind-protect
  1825. (while (not (memq cmd
  1826. '(exit-minibuffer viper-exit-minibuffer)))
  1827. (setq cmd
  1828. (key-binding (setq key (read-key-sequence nil))))
  1829. (cond ((eq cmd 'self-insert-command)
  1830. (if (featurep 'xemacs)
  1831. (insert (events-to-keys key)) ; xemacs
  1832. (insert key) ; emacs
  1833. ))
  1834. ((memq cmd '(exit-minibuffer viper-exit-minibuffer))
  1835. nil)
  1836. (t (command-execute cmd)))
  1837. )))
  1838. ))))
  1839. (defun viper-minibuffer-trim-tail ()
  1840. "Delete junk at the end of the first line of the minibuffer input.
  1841. Remove this function from `viper-minibuffer-exit-hook', if this causes
  1842. problems."
  1843. (if (viper-is-in-minibuffer)
  1844. (let ((inhibit-field-text-motion t))
  1845. (goto-char (viper-minibuffer-real-start))
  1846. (end-of-line)
  1847. (delete-region (point) (point-max)))))
  1848. ;;; Reading string with history
  1849. (defun viper-read-string-with-history (prompt &optional viper-initial
  1850. history-var default keymap
  1851. init-message)
  1852. ;; Read string, prompting with PROMPT and inserting the VIPER-INITIAL
  1853. ;; value. Uses HISTORY-VAR. DEFAULT is the default value to accept if the
  1854. ;; input is an empty string.
  1855. ;; Default value is displayed until the user types something in the
  1856. ;; minibuffer.
  1857. ;; KEYMAP is used, if given, instead of minibuffer-local-map.
  1858. ;; INIT-MESSAGE is the message temporarily displayed after entering the
  1859. ;; minibuffer.
  1860. (let ((minibuffer-setup-hook
  1861. ;; stolen from add-hook
  1862. (let ((old
  1863. (if (boundp 'minibuffer-setup-hook)
  1864. minibuffer-setup-hook
  1865. nil)))
  1866. (cons
  1867. 'viper-minibuffer-standard-hook
  1868. (if (or (not (listp old)) (eq (car old) 'lambda))
  1869. (list old) old))))
  1870. (val "")
  1871. (padding "")
  1872. temp-msg)
  1873. (setq keymap (or keymap minibuffer-local-map)
  1874. viper-initial (or viper-initial "")
  1875. temp-msg (if default
  1876. (format "(default %s) " default)
  1877. ""))
  1878. (setq viper-incomplete-ex-cmd nil)
  1879. (setq val (read-from-minibuffer prompt
  1880. (concat temp-msg viper-initial val padding)
  1881. keymap nil history-var))
  1882. (setq minibuffer-setup-hook nil
  1883. padding (viper-array-to-string (this-command-keys))
  1884. temp-msg "")
  1885. ;; the following tries to be smart about what to put in history
  1886. (if (not (string= val (car (eval history-var))))
  1887. (set history-var (cons val (eval history-var))))
  1888. (if (or (string= (nth 0 (eval history-var)) (nth 1 (eval history-var)))
  1889. (string= (nth 0 (eval history-var)) ""))
  1890. (set history-var (cdr (eval history-var))))
  1891. ;; If the user enters nothing but the prev cmd wasn't viper-ex,
  1892. ;; viper-command-argument, or `! shell-command', this probably means
  1893. ;; that the user typed something then erased. Return "" in this case, not
  1894. ;; the default---the default is too confusing in this case.
  1895. (cond ((and (string= val "")
  1896. (not (string= prompt "!")) ; was a `! shell-command'
  1897. (not (memq last-command
  1898. '(viper-ex
  1899. viper-command-argument
  1900. t)
  1901. )))
  1902. "")
  1903. ((string= val "") (or default ""))
  1904. (t val))
  1905. ))
  1906. ;; insertion commands
  1907. ;; Called when state changes from Insert Vi command mode.
  1908. ;; Repeats the insertion command if Insert state was entered with prefix
  1909. ;; argument > 1.
  1910. (defun viper-repeat-insert-command ()
  1911. (let ((i-com (car viper-d-com))
  1912. (val (nth 1 viper-d-com))
  1913. (char (nth 2 viper-d-com)))
  1914. (if (and val (> val 1)) ; first check that val is non-nil
  1915. (progn
  1916. (setq viper-d-com (list i-com (1- val) ?r nil nil nil))
  1917. (viper-repeat nil)
  1918. (setq viper-d-com (list i-com val char nil nil nil))
  1919. ))))
  1920. (defun viper-insert (arg)
  1921. "Insert before point."
  1922. (interactive "P")
  1923. (viper-set-complex-command-for-undo)
  1924. (let ((val (viper-p-val arg))
  1925. ;;(com (viper-getcom arg))
  1926. )
  1927. (viper-set-destructive-command (list 'viper-insert val ?r nil nil nil))
  1928. (if (eq viper-intermediate-command 'viper-repeat)
  1929. (viper-loop val (viper-yank-last-insertion))
  1930. (viper-change-state-to-insert))))
  1931. (defun viper-append (arg)
  1932. "Append after point."
  1933. (interactive "P")
  1934. (viper-set-complex-command-for-undo)
  1935. (let ((val (viper-p-val arg))
  1936. ;;(com (viper-getcom arg))
  1937. )
  1938. (viper-set-destructive-command (list 'viper-append val ?r nil nil nil))
  1939. (if (not (eolp)) (forward-char))
  1940. (if (eq viper-intermediate-command 'viper-repeat)
  1941. (viper-loop val (viper-yank-last-insertion))
  1942. (viper-change-state-to-insert))))
  1943. (defun viper-Append (arg)
  1944. "Append at end of line."
  1945. (interactive "P")
  1946. (viper-set-complex-command-for-undo)
  1947. (let ((val (viper-p-val arg))
  1948. ;;(com (viper-getcom arg))
  1949. )
  1950. (viper-set-destructive-command (list 'viper-Append val ?r nil nil nil))
  1951. (end-of-line)
  1952. (if (eq viper-intermediate-command 'viper-repeat)
  1953. (viper-loop val (viper-yank-last-insertion))
  1954. (viper-change-state-to-insert))))
  1955. (defun viper-Insert (arg)
  1956. "Insert before first non-white."
  1957. (interactive "P")
  1958. (viper-set-complex-command-for-undo)
  1959. (let ((val (viper-p-val arg))
  1960. ;;(com (viper-getcom arg))
  1961. )
  1962. (viper-set-destructive-command (list 'viper-Insert val ?r nil nil nil))
  1963. (back-to-indentation)
  1964. (if (eq viper-intermediate-command 'viper-repeat)
  1965. (viper-loop val (viper-yank-last-insertion))
  1966. (viper-change-state-to-insert))))
  1967. (defun viper-open-line (arg)
  1968. "Open line below."
  1969. (interactive "P")
  1970. (viper-set-complex-command-for-undo)
  1971. (let ((val (viper-p-val arg))
  1972. ;;(com (viper-getcom arg))
  1973. )
  1974. (viper-set-destructive-command (list 'viper-open-line val ?r nil nil nil))
  1975. (let ((col (current-indentation)))
  1976. (if (eq viper-intermediate-command 'viper-repeat)
  1977. (viper-loop val
  1978. (end-of-line)
  1979. (newline 1)
  1980. (viper-indent-line col)
  1981. (viper-yank-last-insertion))
  1982. (end-of-line)
  1983. (newline 1)
  1984. (viper-indent-line col)
  1985. (viper-change-state-to-insert)))))
  1986. (defun viper-Open-line (arg)
  1987. "Open line above."
  1988. (interactive "P")
  1989. (viper-set-complex-command-for-undo)
  1990. (let ((val (viper-p-val arg))
  1991. ;;(com (viper-getcom arg))
  1992. )
  1993. (viper-set-destructive-command (list 'viper-Open-line val ?r nil nil nil))
  1994. (let ((col (current-indentation)))
  1995. (if (eq viper-intermediate-command 'viper-repeat)
  1996. (viper-loop val
  1997. (beginning-of-line)
  1998. (open-line 1)
  1999. (viper-indent-line col)
  2000. (viper-yank-last-insertion))
  2001. (beginning-of-line)
  2002. (open-line 1)
  2003. (viper-indent-line col)
  2004. (viper-change-state-to-insert)))))
  2005. (defun viper-open-line-at-point (arg)
  2006. "Open line at 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
  2013. (list 'viper-open-line-at-point val ?r nil nil nil))
  2014. (if (eq viper-intermediate-command 'viper-repeat)
  2015. (viper-loop val
  2016. (open-line 1)
  2017. (viper-yank-last-insertion))
  2018. (open-line 1)
  2019. (viper-change-state-to-insert))))
  2020. ;; bound to s
  2021. (defun viper-substitute (arg)
  2022. "Substitute characters."
  2023. (interactive "P")
  2024. (let ((val (viper-p-val arg))
  2025. ;;(com (viper-getcom arg))
  2026. )
  2027. (push-mark nil t)
  2028. (forward-char val)
  2029. (if (eq viper-intermediate-command 'viper-repeat)
  2030. (viper-change-subr (mark t) (point))
  2031. (viper-change (mark t) (point)))
  2032. ;; com is set to ?r when we repeat this command with dot
  2033. (viper-set-destructive-command (list 'viper-substitute val ?r nil nil nil))
  2034. ))
  2035. ;; Command bound to S
  2036. (defun viper-substitute-line (arg)
  2037. "Substitute lines."
  2038. (interactive "p")
  2039. (viper-set-complex-command-for-undo)
  2040. (viper-line (cons arg ?C)))
  2041. ;; Prepare for replace
  2042. (defun viper-start-replace ()
  2043. (setq viper-began-as-replace t
  2044. viper-sitting-in-replace t
  2045. viper-replace-chars-to-delete 0)
  2046. (add-hook
  2047. 'viper-after-change-functions 'viper-replace-mode-spy-after t 'local)
  2048. (add-hook
  2049. 'viper-before-change-functions 'viper-replace-mode-spy-before t 'local)
  2050. ;; this will get added repeatedly, but no harm
  2051. (add-hook 'after-change-functions 'viper-after-change-sentinel t)
  2052. (add-hook 'before-change-functions 'viper-before-change-sentinel t)
  2053. (viper-move-marker-locally
  2054. 'viper-last-posn-in-replace-region (viper-replace-start))
  2055. (add-hook
  2056. 'viper-post-command-hooks 'viper-replace-state-post-command-sentinel
  2057. t 'local)
  2058. (add-hook
  2059. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel t 'local)
  2060. ;; guard against a smarty who switched from R-replace to normal replace
  2061. (remove-hook
  2062. 'viper-post-command-hooks 'viper-R-state-post-command-sentinel 'local)
  2063. (if overwrite-mode (overwrite-mode -1))
  2064. )
  2065. (defun viper-replace-mode-spy-before (beg end)
  2066. (setq viper-replace-region-chars-deleted (viper-chars-in-region beg end))
  2067. )
  2068. ;; Invoked as an after-change-function to calculate how many chars have to be
  2069. ;; deleted. This function may be called several times within a single command,
  2070. ;; if this command performs several separate buffer changes. Therefore, if
  2071. ;; adds up the number of chars inserted and subtracts the number of chars
  2072. ;; deleted.
  2073. (defun viper-replace-mode-spy-after (beg end length)
  2074. (if (memq viper-intermediate-command
  2075. '(dabbrev-expand hippie-expand repeating-insertion-from-ring))
  2076. ;; Take special care of text insertion from insertion ring inside
  2077. ;; replacement overlays.
  2078. (progn
  2079. (setq viper-replace-chars-to-delete 0)
  2080. (viper-move-marker-locally
  2081. 'viper-last-posn-in-replace-region (point)))
  2082. (let* ((real-end (min end (viper-replace-end)))
  2083. (column-shift (- (save-excursion (goto-char real-end)
  2084. (current-column))
  2085. (save-excursion (goto-char beg)
  2086. (current-column))))
  2087. (chars-deleted 0))
  2088. (if (> length 0)
  2089. (setq chars-deleted viper-replace-region-chars-deleted))
  2090. (setq viper-replace-region-chars-deleted 0)
  2091. (setq viper-replace-chars-to-delete
  2092. (+ viper-replace-chars-to-delete
  2093. (-
  2094. ;; if column shift is bigger, due to a TAB insertion, take
  2095. ;; column-shift instead of the number of inserted chars
  2096. (max (viper-chars-in-region beg real-end)
  2097. ;; This test accounts for Chinese/Japanese/... chars,
  2098. ;; which occupy 2 columns instead of one. If we use
  2099. ;; column-shift here, we may delete two chars instead of
  2100. ;; one when the user types one Chinese character.
  2101. ;; Deleting two would be OK, if they were European chars,
  2102. ;; but it is not OK if they are Chinese chars.
  2103. ;; Since it is hard to
  2104. ;; figure out which characters are being deleted in any
  2105. ;; given region, we decided to treat Eastern and European
  2106. ;; characters equally, even though Eastern chars may
  2107. ;; occupy more columns.
  2108. (if (memq this-command '(self-insert-command
  2109. quoted-insert viper-insert-tab))
  2110. column-shift
  2111. 0))
  2112. ;; the number of deleted chars
  2113. chars-deleted)))
  2114. (viper-move-marker-locally
  2115. 'viper-last-posn-in-replace-region
  2116. (max (if (> end (viper-replace-end)) (viper-replace-end) end)
  2117. (or (marker-position viper-last-posn-in-replace-region)
  2118. (viper-replace-start))
  2119. ))
  2120. )))
  2121. ;; Delete stuff between viper-last-posn-in-replace-region and the end of
  2122. ;; viper-replace-overlay-marker, if viper-last-posn-in-replace-region is within
  2123. ;; the overlay and current point is before the end of the overlay.
  2124. ;; Don't delete anything if current point is past the end of the overlay.
  2125. (defun viper-finish-change ()
  2126. (remove-hook
  2127. 'viper-after-change-functions 'viper-replace-mode-spy-after 'local)
  2128. (remove-hook
  2129. 'viper-before-change-functions 'viper-replace-mode-spy-before 'local)
  2130. (remove-hook
  2131. 'viper-post-command-hooks 'viper-replace-state-post-command-sentinel 'local)
  2132. (remove-hook
  2133. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel 'local)
  2134. (viper-restore-cursor-color 'after-replace-mode)
  2135. (setq viper-sitting-in-replace nil) ; just in case we'll need to know it
  2136. (save-excursion
  2137. (if (and viper-replace-overlay
  2138. (viper-pos-within-region viper-last-posn-in-replace-region
  2139. (viper-replace-start)
  2140. (viper-replace-end))
  2141. (< (point) (viper-replace-end)))
  2142. (delete-region
  2143. viper-last-posn-in-replace-region (viper-replace-end))))
  2144. (if (eq viper-current-state 'replace-state)
  2145. (viper-downgrade-to-insert))
  2146. ;; replace mode ended => nullify viper-last-posn-in-replace-region
  2147. (viper-move-marker-locally 'viper-last-posn-in-replace-region nil)
  2148. (viper-hide-replace-overlay)
  2149. (viper-refresh-mode-line)
  2150. (viper-put-string-on-kill-ring viper-last-replace-region)
  2151. )
  2152. ;; Make STRING be the first element of the kill ring.
  2153. (defun viper-put-string-on-kill-ring (string)
  2154. (setq kill-ring (cons string kill-ring))
  2155. (if (> (length kill-ring) kill-ring-max)
  2156. (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
  2157. (setq kill-ring-yank-pointer kill-ring))
  2158. (defun viper-finish-R-mode ()
  2159. (remove-hook
  2160. 'viper-post-command-hooks 'viper-R-state-post-command-sentinel 'local)
  2161. (remove-hook
  2162. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel 'local)
  2163. (viper-downgrade-to-insert))
  2164. (defun viper-start-R-mode ()
  2165. ;; Leave arg as 1, not t: XEmacs insists that it must be a pos number
  2166. (overwrite-mode 1)
  2167. (add-hook
  2168. 'viper-post-command-hooks 'viper-R-state-post-command-sentinel t 'local)
  2169. (add-hook
  2170. 'viper-pre-command-hooks 'viper-replace-state-pre-command-sentinel t 'local)
  2171. ;; guard against a smarty who switched from R-replace to normal replace
  2172. (remove-hook
  2173. 'viper-post-command-hooks 'viper-replace-state-post-command-sentinel 'local)
  2174. )
  2175. (defun viper-replace-state-exit-cmd ()
  2176. "Binding for keys that cause Replace state to switch to Vi or to Insert.
  2177. These keys are ESC, RET, and LineFeed."
  2178. (interactive)
  2179. (if overwrite-mode ; if in replace mode invoked via 'R'
  2180. (viper-finish-R-mode)
  2181. (viper-finish-change))
  2182. (let (com)
  2183. (if (eq this-command 'viper-intercept-ESC-key)
  2184. (setq com 'viper-exit-insert-state)
  2185. (viper-set-unread-command-events last-input-event)
  2186. (setq com (key-binding (viper-read-key-sequence nil))))
  2187. (condition-case conds
  2188. (command-execute com)
  2189. (error
  2190. (viper-message-conditions conds)))
  2191. )
  2192. (viper-hide-replace-overlay))
  2193. (defun viper-replace-state-carriage-return ()
  2194. "Carriage return in Viper replace state."
  2195. (interactive)
  2196. ;; If Emacs start supporting overlay maps, as it currently supports
  2197. ;; text-property maps, we could do away with viper-replace-minor-mode and
  2198. ;; just have keymap attached to replace overlay. Then the "if part" of this
  2199. ;; statement can be deleted.
  2200. (if (or (< (point) (viper-replace-start))
  2201. (> (point) (viper-replace-end)))
  2202. (let (viper-replace-minor-mode com)
  2203. (viper-set-unread-command-events last-input-event)
  2204. (setq com (key-binding (read-key-sequence nil)))
  2205. (condition-case conds
  2206. (command-execute com)
  2207. (error
  2208. (viper-message-conditions conds))))
  2209. (if (not viper-allow-multiline-replace-regions)
  2210. (viper-replace-state-exit-cmd)
  2211. (if (viper-same-line (point) (viper-replace-end))
  2212. (viper-replace-state-exit-cmd)
  2213. ;; delete the rest of line
  2214. (delete-region (point) (viper-line-pos 'end))
  2215. (save-excursion
  2216. (end-of-line)
  2217. (if (eobp) (error "Last line in buffer")))
  2218. ;; skip to the next line
  2219. (forward-line 1)
  2220. (back-to-indentation)
  2221. ))))
  2222. ;; This is the function bound to 'R'---unlimited replace.
  2223. ;; Similar to Emacs's own overwrite-mode.
  2224. (defun viper-overwrite (arg)
  2225. "Begin overwrite mode."
  2226. (interactive "P")
  2227. (let ((val (viper-p-val arg))
  2228. ;;(com (viper-getcom arg))
  2229. (len))
  2230. (viper-set-destructive-command (list 'viper-overwrite val ?r nil nil nil))
  2231. (if (eq viper-intermediate-command 'viper-repeat)
  2232. (progn
  2233. ;; Viper saves inserted text in viper-last-insertion
  2234. (setq len (length viper-last-insertion))
  2235. (delete-char (min len (- (point-max) (point) 1)))
  2236. (viper-loop val (viper-yank-last-insertion)))
  2237. (setq last-command 'viper-overwrite)
  2238. (viper-set-complex-command-for-undo)
  2239. (viper-set-replace-overlay (point) (viper-line-pos 'end))
  2240. (viper-change-state-to-replace)
  2241. )))
  2242. ;; line commands
  2243. (defun viper-line (arg)
  2244. (let ((val (car arg))
  2245. (com (cdr arg)))
  2246. (viper-move-marker-locally 'viper-com-point (point))
  2247. (if (not (eobp))
  2248. (viper-next-line-carefully (1- val)))
  2249. ;; the following ensures that dd, cc, D, yy will do the right thing on the
  2250. ;; last line of buffer when this line has no \n.
  2251. (viper-add-newline-at-eob-if-necessary)
  2252. (viper-execute-com 'viper-line val com))
  2253. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2254. )
  2255. (defun viper-yank-line (arg)
  2256. "Yank ARG lines (in Vi's sense)."
  2257. (interactive "P")
  2258. (let ((val (viper-p-val arg)))
  2259. (viper-line (cons val ?Y))))
  2260. ;; region commands
  2261. (defun viper-region (arg)
  2262. "Execute command on a region."
  2263. (interactive "P")
  2264. (let ((val (viper-P-val arg))
  2265. (com (viper-getcom arg)))
  2266. (viper-move-marker-locally 'viper-com-point (point))
  2267. (exchange-point-and-mark)
  2268. (viper-execute-com 'viper-region val com)))
  2269. (defun viper-Region (arg)
  2270. "Execute command on a Region."
  2271. (interactive "P")
  2272. (let ((val (viper-P-val arg))
  2273. (com (viper-getCom arg)))
  2274. (viper-move-marker-locally 'viper-com-point (point))
  2275. (exchange-point-and-mark)
  2276. (viper-execute-com 'viper-Region val com)))
  2277. (defun viper-replace-char (arg)
  2278. "Replace the following ARG chars by the character read."
  2279. (interactive "P")
  2280. (if (and (eolp) (bolp)) (error "No character to replace here"))
  2281. (let ((val (viper-p-val arg))
  2282. (com (viper-getcom arg)))
  2283. (viper-replace-char-subr com val)
  2284. (if (and (eolp) (not (bolp))) (forward-char 1))
  2285. (setq viper-this-command-keys
  2286. (format "%sr" (if (integerp arg) arg "")))
  2287. (viper-set-destructive-command
  2288. (list 'viper-replace-char val ?r nil viper-d-char nil))
  2289. ))
  2290. (defun viper-replace-char-subr (com arg)
  2291. (let ((inhibit-quit t)
  2292. char)
  2293. (viper-set-complex-command-for-undo)
  2294. (or (eq viper-intermediate-command 'viper-repeat)
  2295. (viper-special-read-and-insert-char))
  2296. (delete-char 1 t)
  2297. (setq char (if com viper-d-char (viper-char-at-pos 'backward)))
  2298. (if com (insert char))
  2299. (setq viper-d-char char)
  2300. (viper-loop (1- (if (> arg 0) arg (- arg)))
  2301. (delete-char 1 t)
  2302. (insert char))
  2303. (viper-adjust-undo)
  2304. (backward-char arg)
  2305. ))
  2306. ;; basic cursor movement. j, k, l, h commands.
  2307. (defun viper-forward-char (arg)
  2308. "Move point right ARG characters (left if ARG negative).
  2309. On reaching end of line, stop and signal error."
  2310. (interactive "P")
  2311. (viper-leave-region-active)
  2312. (let ((val (viper-p-val arg))
  2313. (com (viper-getcom arg)))
  2314. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2315. (if viper-ex-style-motion
  2316. (progn
  2317. ;; the boundary condition check gets weird here because
  2318. ;; forward-char may be the parameter of a delete, and 'dl' works
  2319. ;; just like 'x' for the last char on a line, so we have to allow
  2320. ;; the forward motion before the 'viper-execute-com', but, of
  2321. ;; course, 'dl' doesn't work on an empty line, so we have to
  2322. ;; catch that condition before 'viper-execute-com'
  2323. (if (and (eolp) (bolp)) (error "Viper bell") (forward-char val))
  2324. (if com (viper-execute-com 'viper-forward-char val com))
  2325. (if (eolp) (progn (backward-char 1) (error "Viper bell"))))
  2326. (forward-char val)
  2327. (if com (viper-execute-com 'viper-forward-char val com)))))
  2328. (defun viper-backward-char (arg)
  2329. "Move point left ARG characters (right if ARG negative).
  2330. On reaching beginning of line, stop and signal error."
  2331. (interactive "P")
  2332. (viper-leave-region-active)
  2333. (let ((val (viper-p-val arg))
  2334. (com (viper-getcom arg)))
  2335. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2336. (if viper-ex-style-motion
  2337. (progn
  2338. (if (bolp) (error "Viper bell") (backward-char val))
  2339. (if com (viper-execute-com 'viper-backward-char val com)))
  2340. (backward-char val)
  2341. (if com (viper-execute-com 'viper-backward-char val com)))))
  2342. ;; Like forward-char, but doesn't move at end of buffer.
  2343. ;; Returns distance traveled
  2344. ;; (positive or 0, if arg positive; negative if arg negative).
  2345. (defun viper-forward-char-carefully (&optional arg)
  2346. (setq arg (or arg 1))
  2347. (let ((pt (point)))
  2348. (condition-case nil
  2349. (forward-char arg)
  2350. (error nil))
  2351. (if (< (point) pt) ; arg was negative
  2352. (- (viper-chars-in-region pt (point)))
  2353. (viper-chars-in-region pt (point)))))
  2354. ;; Like backward-char, but doesn't move at beg of buffer.
  2355. ;; Returns distance traveled
  2356. ;; (negative or 0, if arg positive; positive if arg negative).
  2357. (defun viper-backward-char-carefully (&optional arg)
  2358. (setq arg (or arg 1))
  2359. (let ((pt (point)))
  2360. (condition-case nil
  2361. (backward-char arg)
  2362. (error nil))
  2363. (if (> (point) pt) ; arg was negative
  2364. (viper-chars-in-region pt (point))
  2365. (- (viper-chars-in-region pt (point))))))
  2366. (defun viper-next-line-carefully (arg)
  2367. (condition-case nil
  2368. ;; do not use forward-line! need to keep column
  2369. (let ((line-move-visual nil))
  2370. (if (featurep 'emacs)
  2371. (with-no-warnings (next-line arg))
  2372. (next-line arg)))
  2373. (error nil)))
  2374. ;;; Word command
  2375. ;; Words are formed from alpha's and nonalphas - <sp>,\t\n are separators for
  2376. ;; word movement. When executed with a destructive command, \n is usually left
  2377. ;; untouched for the last word. Viper uses syntax table to determine what is a
  2378. ;; word and what is a separator. However, \n is always a separator. Also, if
  2379. ;; viper-syntax-preference is 'vi, then `_' is part of the word.
  2380. ;; skip only one \n
  2381. (defun viper-skip-separators (forward)
  2382. (if forward
  2383. (progn
  2384. (viper-skip-all-separators-forward 'within-line)
  2385. (if (looking-at "\n")
  2386. (progn
  2387. (forward-char)
  2388. (viper-skip-all-separators-forward 'within-line))))
  2389. ;; check for eob and white space before it. move off of eob
  2390. (if (and (eobp) (save-excursion
  2391. (viper-backward-char-carefully)
  2392. (viper-looking-at-separator)))
  2393. (viper-backward-char-carefully))
  2394. (viper-skip-all-separators-backward 'within-line)
  2395. (viper-backward-char-carefully)
  2396. (if (looking-at "\n")
  2397. (viper-skip-all-separators-backward 'within-line)
  2398. (or (viper-looking-at-separator) (forward-char)))))
  2399. (defun viper-forward-word-kernel (val)
  2400. (while (> val 0)
  2401. (cond ((viper-looking-at-alpha)
  2402. (viper-skip-alpha-forward "_")
  2403. (viper-skip-separators t))
  2404. ((viper-looking-at-separator)
  2405. (viper-skip-separators t))
  2406. ((not (viper-looking-at-alphasep))
  2407. (viper-skip-nonalphasep-forward)
  2408. (viper-skip-separators t)))
  2409. (setq val (1- val))))
  2410. ;; first skip non-newline separators backward, then skip \n. Then, if TWICE is
  2411. ;; non-nil, skip non-\n back again, but don't overshoot the limit LIM.
  2412. (defun viper-separator-skipback-special (twice lim)
  2413. (let ((prev-char (viper-char-at-pos 'backward))
  2414. (saved-point (point)))
  2415. ;; skip non-newline separators backward
  2416. (while (and (not (viper-memq-char prev-char '(nil \n)))
  2417. (< lim (point))
  2418. ;; must be non-newline separator
  2419. (if (eq viper-syntax-preference 'strict-vi)
  2420. (viper-memq-char prev-char '(?\ ?\t))
  2421. (viper-memq-char (char-syntax prev-char) '(?\ ?-))))
  2422. (viper-backward-char-carefully)
  2423. (setq prev-char (viper-char-at-pos 'backward)))
  2424. (if (and (< lim (point)) (eq prev-char ?\n))
  2425. (backward-char)
  2426. ;; If we skipped to the next word and the prefix of this line doesn't
  2427. ;; consist of separators preceded by a newline, then don't skip backwards
  2428. ;; at all.
  2429. (goto-char saved-point))
  2430. (setq prev-char (viper-char-at-pos 'backward))
  2431. ;; skip again, but make sure we don't overshoot the limit
  2432. (if twice
  2433. (while (and (not (viper-memq-char prev-char '(nil \n)))
  2434. (< lim (point))
  2435. ;; must be non-newline separator
  2436. (if (eq viper-syntax-preference 'strict-vi)
  2437. (viper-memq-char prev-char '(?\ ?\t))
  2438. (viper-memq-char (char-syntax prev-char) '(?\ ?-))))
  2439. (viper-backward-char-carefully)
  2440. (setq prev-char (viper-char-at-pos 'backward))))
  2441. (if (= (point) lim)
  2442. (viper-forward-char-carefully))
  2443. ))
  2444. (defun viper-forward-word (arg)
  2445. "Forward word."
  2446. (interactive "P")
  2447. (viper-leave-region-active)
  2448. (let ((val (viper-p-val arg))
  2449. (com (viper-getcom arg)))
  2450. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2451. (viper-forward-word-kernel val)
  2452. (if com
  2453. (progn
  2454. (cond ((viper-char-equal com ?c)
  2455. (viper-separator-skipback-special 'twice viper-com-point))
  2456. ;; Yank words including the whitespace, but not newline
  2457. ((viper-char-equal com ?y)
  2458. (viper-separator-skipback-special nil viper-com-point))
  2459. ((viper-dotable-command-p com)
  2460. (viper-separator-skipback-special nil viper-com-point)))
  2461. (viper-execute-com 'viper-forward-word val com)))
  2462. ))
  2463. (defun viper-forward-Word (arg)
  2464. "Forward word delimited by white characters."
  2465. (interactive "P")
  2466. (viper-leave-region-active)
  2467. (let ((val (viper-p-val arg))
  2468. (com (viper-getcom arg)))
  2469. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2470. (viper-loop val
  2471. (viper-skip-nonseparators 'forward)
  2472. (viper-skip-separators t))
  2473. (if com (progn
  2474. (cond ((viper-char-equal com ?c)
  2475. (viper-separator-skipback-special 'twice viper-com-point))
  2476. ;; Yank words including the whitespace, but not newline
  2477. ((viper-char-equal com ?y)
  2478. (viper-separator-skipback-special nil viper-com-point))
  2479. ((viper-dotable-command-p com)
  2480. (viper-separator-skipback-special nil viper-com-point)))
  2481. (viper-execute-com 'viper-forward-Word val com)))))
  2482. ;; this is a bit different from Vi, but Vi's end of word
  2483. ;; makes no sense whatsoever
  2484. (defun viper-end-of-word-kernel ()
  2485. (if (viper-end-of-word-p) (forward-char))
  2486. (if (viper-looking-at-separator)
  2487. (viper-skip-all-separators-forward))
  2488. (cond ((viper-looking-at-alpha) (viper-skip-alpha-forward "_"))
  2489. ((not (viper-looking-at-alphasep)) (viper-skip-nonalphasep-forward)))
  2490. (viper-backward-char-carefully))
  2491. (defun viper-end-of-word-p ()
  2492. (or (eobp)
  2493. (save-excursion
  2494. (cond ((viper-looking-at-alpha)
  2495. (forward-char)
  2496. (not (viper-looking-at-alpha)))
  2497. ((not (viper-looking-at-alphasep))
  2498. (forward-char)
  2499. (viper-looking-at-alphasep))))))
  2500. (defun viper-end-of-word (arg &optional careful)
  2501. "Move point to end of current word."
  2502. (interactive "P")
  2503. (viper-leave-region-active)
  2504. (let ((val (viper-p-val arg))
  2505. (com (viper-getcom arg)))
  2506. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2507. (viper-loop val (viper-end-of-word-kernel))
  2508. (if com
  2509. (progn
  2510. (forward-char)
  2511. (viper-execute-com 'viper-end-of-word val com)))))
  2512. (defun viper-end-of-Word (arg)
  2513. "Forward to end of word delimited by white character."
  2514. (interactive "P")
  2515. (viper-leave-region-active)
  2516. (let ((val (viper-p-val arg))
  2517. (com (viper-getcom arg)))
  2518. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2519. (viper-loop val
  2520. (viper-end-of-word-kernel)
  2521. (viper-skip-nonseparators 'forward)
  2522. (backward-char))
  2523. (if com
  2524. (progn
  2525. (forward-char)
  2526. (viper-execute-com 'viper-end-of-Word val com)))))
  2527. (defun viper-backward-word-kernel (val)
  2528. (while (> val 0)
  2529. (viper-backward-char-carefully)
  2530. (cond ((viper-looking-at-alpha)
  2531. (viper-skip-alpha-backward "_"))
  2532. ((viper-looking-at-separator)
  2533. (forward-char)
  2534. (viper-skip-separators nil)
  2535. (viper-backward-char-carefully)
  2536. (cond ((viper-looking-at-alpha)
  2537. (viper-skip-alpha-backward "_"))
  2538. ((not (viper-looking-at-alphasep))
  2539. (viper-skip-nonalphasep-backward))
  2540. ((bobp)) ; could still be at separator, but at beg of buffer
  2541. (t (forward-char))))
  2542. ((not (viper-looking-at-alphasep))
  2543. (viper-skip-nonalphasep-backward)))
  2544. (setq val (1- val))))
  2545. (defun viper-backward-word (arg)
  2546. "Backward word."
  2547. (interactive "P")
  2548. (viper-leave-region-active)
  2549. (let ((val (viper-p-val arg))
  2550. (com (viper-getcom arg)))
  2551. (if com
  2552. (let (i)
  2553. (if (setq i (save-excursion (backward-char) (looking-at "\n")))
  2554. (backward-char))
  2555. (viper-move-marker-locally 'viper-com-point (point))
  2556. (if i (forward-char))))
  2557. (viper-backward-word-kernel val)
  2558. (if com (viper-execute-com 'viper-backward-word val com))))
  2559. (defun viper-backward-Word (arg)
  2560. "Backward word delimited by white character."
  2561. (interactive "P")
  2562. (viper-leave-region-active)
  2563. (let ((val (viper-p-val arg))
  2564. (com (viper-getcom arg)))
  2565. (if com
  2566. (let (i)
  2567. (if (setq i (save-excursion (backward-char) (looking-at "\n")))
  2568. (backward-char))
  2569. (viper-move-marker-locally 'viper-com-point (point))
  2570. (if i (forward-char))))
  2571. (viper-loop val
  2572. (viper-skip-separators nil) ; nil means backward here
  2573. (viper-skip-nonseparators 'backward))
  2574. (if com (viper-execute-com 'viper-backward-Word val com))))
  2575. ;; line commands
  2576. (defun viper-beginning-of-line (arg)
  2577. "Go to beginning of line."
  2578. (interactive "P")
  2579. (viper-leave-region-active)
  2580. (let ((val (viper-p-val arg))
  2581. (com (viper-getcom arg)))
  2582. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2583. (beginning-of-line val)
  2584. (if com (viper-execute-com 'viper-beginning-of-line val com))))
  2585. (defun viper-bol-and-skip-white (arg)
  2586. "Beginning of line at first non-white character."
  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. (forward-to-indentation (1- val))
  2593. (if com (viper-execute-com 'viper-bol-and-skip-white val com))))
  2594. (defun viper-goto-eol (arg)
  2595. "Go to end of line."
  2596. (interactive "P")
  2597. (viper-leave-region-active)
  2598. (let ((val (viper-p-val arg))
  2599. (com (viper-getcom arg)))
  2600. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2601. (end-of-line val)
  2602. (if com (viper-execute-com 'viper-goto-eol val com))
  2603. (if viper-ex-style-motion
  2604. (if (and (eolp) (not (bolp))
  2605. ;; a fix for viper-change-to-eol
  2606. (not (equal viper-current-state 'insert-state)))
  2607. (backward-char 1)
  2608. ))))
  2609. (defun viper-goto-col (arg)
  2610. "Go to ARG's column."
  2611. (interactive "P")
  2612. (viper-leave-region-active)
  2613. (let ((val (viper-p-val arg))
  2614. (com (viper-getcom arg))
  2615. line-len)
  2616. (setq line-len
  2617. (viper-chars-in-region
  2618. (viper-line-pos 'start) (viper-line-pos 'end)))
  2619. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2620. (beginning-of-line)
  2621. (forward-char (1- (min line-len val)))
  2622. (while (> (current-column) (1- val))
  2623. (backward-char 1))
  2624. (if com (viper-execute-com 'viper-goto-col val com))
  2625. (save-excursion
  2626. (end-of-line)
  2627. (if (> val (current-column)) (error "Viper bell")))
  2628. ))
  2629. (defun viper-next-line (arg)
  2630. "Go to next line."
  2631. (interactive "P")
  2632. (viper-leave-region-active)
  2633. (let ((val (viper-p-val arg))
  2634. (com (viper-getCom arg)))
  2635. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2636. ;; do not use forward-line! need to keep column
  2637. (let ((line-move-visual nil))
  2638. (if (featurep 'emacs)
  2639. (with-no-warnings (next-line val))
  2640. (next-line val)))
  2641. (if viper-ex-style-motion
  2642. (if (and (eolp) (not (bolp))) (backward-char 1)))
  2643. (setq this-command 'next-line)
  2644. (if com (viper-execute-com 'viper-next-line val com))))
  2645. (declare-function widget-type "wid-edit" (widget))
  2646. (declare-function widget-button-press "wid-edit" (pos &optional event))
  2647. (declare-function viper-set-hooks "viper" ())
  2648. (defun viper-next-line-at-bol (arg)
  2649. "Next line at beginning of line.
  2650. If point is on a widget or a button, simulate clicking on that widget/button."
  2651. (interactive "P")
  2652. (let* ((field (get-char-property (point) 'field))
  2653. (button (get-char-property (point) 'button))
  2654. (doc (get-char-property (point) 'widget-doc))
  2655. (widget (or field button doc)))
  2656. (if (and widget
  2657. (if (symbolp widget)
  2658. (get widget 'widget-type)
  2659. (and (consp widget)
  2660. (get (widget-type widget) 'widget-type))))
  2661. (widget-button-press (point))
  2662. (if (and (fboundp 'button-at) (fboundp 'push-button) (button-at (point)))
  2663. (push-button)
  2664. ;; not a widget or a button
  2665. (viper-leave-region-active)
  2666. (save-excursion
  2667. (end-of-line)
  2668. (if (eobp) (error "Last line in buffer")))
  2669. (let ((val (viper-p-val arg))
  2670. (com (viper-getCom arg)))
  2671. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2672. (forward-line val)
  2673. (back-to-indentation)
  2674. (if com (viper-execute-com 'viper-next-line-at-bol val com)))))))
  2675. (defun viper-previous-line (arg)
  2676. "Go to previous line."
  2677. (interactive "P")
  2678. (viper-leave-region-active)
  2679. (let ((val (viper-p-val arg))
  2680. (com (viper-getCom arg)))
  2681. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2682. ;; do not use forward-line! need to keep column
  2683. (let ((line-move-visual nil))
  2684. (if (featurep 'emacs)
  2685. (with-no-warnings (previous-line val))
  2686. (previous-line val)))
  2687. (if viper-ex-style-motion
  2688. (if (and (eolp) (not (bolp))) (backward-char 1)))
  2689. (setq this-command 'previous-line)
  2690. (if com (viper-execute-com 'viper-previous-line val com))))
  2691. (defun viper-previous-line-at-bol (arg)
  2692. "Previous line at beginning of line."
  2693. (interactive "P")
  2694. (viper-leave-region-active)
  2695. (save-excursion
  2696. (beginning-of-line)
  2697. (if (bobp) (error "First line in buffer")))
  2698. (let ((val (viper-p-val arg))
  2699. (com (viper-getCom arg)))
  2700. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2701. (forward-line (- val))
  2702. (back-to-indentation)
  2703. (if com (viper-execute-com 'viper-previous-line val com))))
  2704. (defun viper-change-to-eol (arg)
  2705. "Change to end of line."
  2706. (interactive "P")
  2707. (viper-goto-eol (cons arg ?c)))
  2708. (defun viper-kill-line (arg)
  2709. "Delete line."
  2710. (interactive "P")
  2711. (viper-goto-eol (cons arg ?d)))
  2712. (defun viper-erase-line (arg)
  2713. "Erase line."
  2714. (interactive "P")
  2715. (viper-beginning-of-line (cons arg ?d)))
  2716. ;;; Moving around
  2717. (defun viper-goto-line (arg)
  2718. "Go to ARG's line. Without ARG go to end of buffer."
  2719. (interactive "P")
  2720. (let ((val (viper-P-val arg))
  2721. (com (viper-getCom arg)))
  2722. (viper-move-marker-locally 'viper-com-point (point))
  2723. (viper-deactivate-mark)
  2724. (push-mark nil t)
  2725. (if (null val)
  2726. (goto-char (point-max))
  2727. (goto-char (point-min))
  2728. (forward-line (1- val)))
  2729. ;; positioning is done twice: before and after command execution
  2730. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2731. (back-to-indentation)
  2732. (if com (viper-execute-com 'viper-goto-line val com))
  2733. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2734. (back-to-indentation)
  2735. ))
  2736. ;; Find ARG's occurrence of CHAR on the current line.
  2737. ;; If FORWARD then search is forward, otherwise backward. OFFSET is used to
  2738. ;; adjust point after search.
  2739. (defun viper-find-char (arg char forward offset)
  2740. (or (char-or-string-p char) (error "Viper bell"))
  2741. (let ((arg (if forward arg (- arg)))
  2742. (cmd (if (eq viper-intermediate-command 'viper-repeat)
  2743. (nth 5 viper-d-com)
  2744. (viper-array-to-string (this-command-keys))))
  2745. point region-beg region-end)
  2746. (save-excursion
  2747. (save-restriction
  2748. (if (> arg 0) ; forward
  2749. (progn
  2750. (setq region-beg (point))
  2751. (if viper-allow-multiline-replace-regions
  2752. (viper-forward-paragraph 1)
  2753. (end-of-line))
  2754. (setq region-end (point)))
  2755. (setq region-end (point))
  2756. (if viper-allow-multiline-replace-regions
  2757. (viper-backward-paragraph 1)
  2758. (beginning-of-line))
  2759. (setq region-beg (point)))
  2760. (if (or (and (< arg 0)
  2761. (< (- region-end region-beg)
  2762. (if viper-allow-multiline-replace-regions
  2763. 2 1))
  2764. (bolp))
  2765. (and (> arg 0)
  2766. (< (- region-end region-beg)
  2767. (if viper-allow-multiline-replace-regions
  2768. 3 2))
  2769. (eolp)))
  2770. (error "Command `%s': At %s of %s"
  2771. cmd
  2772. (if (> arg 0) "end" "beginning")
  2773. (if viper-allow-multiline-replace-regions
  2774. "paragraph" "line")))
  2775. (narrow-to-region region-beg region-end)
  2776. ;; if arg > 0, point is forwarded before search.
  2777. (if (> arg 0) (goto-char (1+ (point-min)))
  2778. (goto-char (point-max)))
  2779. (if (let ((case-fold-search nil))
  2780. (search-forward (char-to-string char) nil 0 arg))
  2781. (setq point (point))
  2782. (error "Command `%s': `%c' not found" cmd char))))
  2783. (goto-char point)
  2784. (if (> arg 0)
  2785. (backward-char (if offset 2 1))
  2786. (forward-char (if offset 1 0)))))
  2787. (defun viper-find-char-forward (arg)
  2788. "Find char on the line.
  2789. If called interactively read the char to find from the terminal, and if
  2790. called from viper-repeat, the char last used is used. This behavior is
  2791. controlled by the sign of prefix numeric value."
  2792. (interactive "P")
  2793. (let ((val (viper-p-val arg))
  2794. (com (viper-getcom arg))
  2795. (cmd-representation (nth 5 viper-d-com)))
  2796. (if (> val 0)
  2797. ;; this means that the function was called interactively
  2798. (setq viper-f-char (read-char)
  2799. viper-f-forward t
  2800. viper-f-offset nil)
  2801. ;; viper-repeat --- set viper-F-char from command-keys
  2802. (setq viper-F-char (if (stringp cmd-representation)
  2803. (viper-seq-last-elt cmd-representation)
  2804. viper-F-char)
  2805. viper-f-char viper-F-char)
  2806. (setq val (- val)))
  2807. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2808. (viper-find-char
  2809. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) t nil)
  2810. (setq val (- val))
  2811. (if com
  2812. (progn
  2813. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2814. (forward-char)
  2815. (viper-execute-com 'viper-find-char-forward val com)))))
  2816. (defun viper-goto-char-forward (arg)
  2817. "Go up to char ARG forward on line."
  2818. (interactive "P")
  2819. (let ((val (viper-p-val arg))
  2820. (com (viper-getcom arg))
  2821. (cmd-representation (nth 5 viper-d-com)))
  2822. (if (> val 0)
  2823. ;; this means that the function was called interactively
  2824. (setq viper-f-char (read-char)
  2825. viper-f-forward t
  2826. viper-f-offset t)
  2827. ;; viper-repeat --- set viper-F-char from command-keys
  2828. (setq viper-F-char (if (stringp cmd-representation)
  2829. (viper-seq-last-elt cmd-representation)
  2830. viper-F-char)
  2831. viper-f-char viper-F-char)
  2832. (setq val (- val)))
  2833. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2834. (viper-find-char
  2835. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) t t)
  2836. (setq val (- val))
  2837. (if com
  2838. (progn
  2839. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2840. (forward-char)
  2841. (viper-execute-com 'viper-goto-char-forward val com)))))
  2842. (defun viper-find-char-backward (arg)
  2843. "Find char ARG on line backward."
  2844. (interactive "P")
  2845. (let ((val (viper-p-val arg))
  2846. (com (viper-getcom arg))
  2847. (cmd-representation (nth 5 viper-d-com)))
  2848. (if (> val 0)
  2849. ;; this means that the function was called interactively
  2850. (setq viper-f-char (read-char)
  2851. viper-f-forward nil
  2852. viper-f-offset nil)
  2853. ;; viper-repeat --- set viper-F-char from command-keys
  2854. (setq viper-F-char (if (stringp cmd-representation)
  2855. (viper-seq-last-elt cmd-representation)
  2856. viper-F-char)
  2857. viper-f-char viper-F-char)
  2858. (setq val (- val)))
  2859. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2860. (viper-find-char
  2861. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) nil nil)
  2862. (setq val (- val))
  2863. (if com
  2864. (progn
  2865. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2866. (viper-execute-com 'viper-find-char-backward val com)))))
  2867. (defun viper-goto-char-backward (arg)
  2868. "Go up to char ARG backward on line."
  2869. (interactive "P")
  2870. (let ((val (viper-p-val arg))
  2871. (com (viper-getcom arg))
  2872. (cmd-representation (nth 5 viper-d-com)))
  2873. (if (> val 0)
  2874. ;; this means that the function was called interactively
  2875. (setq viper-f-char (read-char)
  2876. viper-f-forward nil
  2877. viper-f-offset t)
  2878. ;; viper-repeat --- set viper-F-char from command-keys
  2879. (setq viper-F-char (if (stringp cmd-representation)
  2880. (viper-seq-last-elt cmd-representation)
  2881. viper-F-char)
  2882. viper-f-char viper-F-char)
  2883. (setq val (- val)))
  2884. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2885. (viper-find-char
  2886. val (if (> (viper-p-val arg) 0) viper-f-char viper-F-char) nil t)
  2887. (setq val (- val))
  2888. (if com
  2889. (progn
  2890. (setq viper-F-char viper-f-char) ; set new viper-F-char
  2891. (viper-execute-com 'viper-goto-char-backward val com)))))
  2892. (defun viper-repeat-find (arg)
  2893. "Repeat previous find command."
  2894. (interactive "P")
  2895. (let ((val (viper-p-val arg))
  2896. (com (viper-getcom arg)))
  2897. (viper-deactivate-mark)
  2898. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2899. (viper-find-char val viper-f-char viper-f-forward viper-f-offset)
  2900. (if com
  2901. (progn
  2902. (if viper-f-forward (forward-char))
  2903. (viper-execute-com 'viper-repeat-find val com)))))
  2904. (defun viper-repeat-find-opposite (arg)
  2905. "Repeat previous find command in the opposite direction."
  2906. (interactive "P")
  2907. (let ((val (viper-p-val arg))
  2908. (com (viper-getcom arg)))
  2909. (viper-deactivate-mark)
  2910. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2911. (viper-find-char val viper-f-char (not viper-f-forward) viper-f-offset)
  2912. (if com
  2913. (progn
  2914. (if viper-f-forward (forward-char))
  2915. (viper-execute-com 'viper-repeat-find-opposite val com)))))
  2916. ;; window scrolling etc.
  2917. (defun viper-window-top (arg)
  2918. "Go to home window line."
  2919. (interactive "P")
  2920. (let ((val (viper-p-val arg))
  2921. (com (viper-getCom arg)))
  2922. (viper-leave-region-active)
  2923. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2924. (push-mark nil t)
  2925. (move-to-window-line (1- val))
  2926. ;; positioning is done twice: before and after command execution
  2927. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2928. (back-to-indentation)
  2929. (if com (viper-execute-com 'viper-window-top val com))
  2930. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2931. (back-to-indentation)
  2932. ))
  2933. (defun viper-window-middle (arg)
  2934. "Go to middle window line."
  2935. (interactive "P")
  2936. (let ((val (viper-p-val arg))
  2937. (com (viper-getCom arg)))
  2938. (viper-leave-region-active)
  2939. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2940. (push-mark nil t)
  2941. (move-to-window-line (+ (/ (1- (window-height)) 2) (1- val)))
  2942. ;; positioning is done twice: before and after command execution
  2943. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2944. (back-to-indentation)
  2945. (if com (viper-execute-com 'viper-window-middle val com))
  2946. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2947. (back-to-indentation)
  2948. ))
  2949. (defun viper-window-bottom (arg)
  2950. "Go to last window line."
  2951. (interactive "P")
  2952. (let ((val (viper-p-val arg))
  2953. (com (viper-getCom arg)))
  2954. (viper-leave-region-active)
  2955. (if com (viper-move-marker-locally 'viper-com-point (point)))
  2956. (push-mark nil t)
  2957. (move-to-window-line (- val))
  2958. ;; positioning is done twice: before and after command execution
  2959. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2960. (back-to-indentation)
  2961. (if com (viper-execute-com 'viper-window-bottom val com))
  2962. (if (and (eobp) (bolp) (not (bobp))) (forward-line -1))
  2963. (back-to-indentation)
  2964. ))
  2965. (defun viper-line-to-top (arg)
  2966. "Put current line on the home line."
  2967. (interactive "p")
  2968. (recenter (1- arg)))
  2969. (defun viper-line-to-middle (arg)
  2970. "Put current line on the middle line."
  2971. (interactive "p")
  2972. (recenter (+ (1- arg) (/ (1- (window-height)) 2))))
  2973. (defun viper-line-to-bottom (arg)
  2974. "Put current line on the last line."
  2975. (interactive "p")
  2976. (recenter (- (window-height) (1+ arg))))
  2977. ;; If point is within viper-search-scroll-threshold of window top or bottom,
  2978. ;; scroll up or down 1/7 of window height, depending on whether we are at the
  2979. ;; bottom or at the top of the window. This function is called by viper-search
  2980. ;; (which is called from viper-search-forward/backward/next). If the value of
  2981. ;; viper-search-scroll-threshold is negative - don't scroll.
  2982. (defun viper-adjust-window ()
  2983. (let ((win-height (if (featurep 'xemacs)
  2984. (window-displayed-height)
  2985. (1- (window-height)))) ; adjust for mode line
  2986. (pt (point))
  2987. at-top-p at-bottom-p
  2988. min-scroll direction)
  2989. (save-excursion
  2990. (move-to-window-line 0) ; top
  2991. (setq at-top-p
  2992. (<= (count-lines pt (point))
  2993. viper-search-scroll-threshold))
  2994. (move-to-window-line -1) ; bottom
  2995. (setq at-bottom-p
  2996. (<= (count-lines pt (point)) viper-search-scroll-threshold)))
  2997. (cond (at-top-p (setq min-scroll (1- viper-search-scroll-threshold)
  2998. direction 1))
  2999. (at-bottom-p (setq min-scroll (1+ viper-search-scroll-threshold)
  3000. direction -1)))
  3001. (if min-scroll
  3002. (recenter
  3003. (* (max min-scroll (/ win-height 7)) direction)))
  3004. ))
  3005. ;; paren match
  3006. ;; must correct this to only match ( to ) etc. On the other hand
  3007. ;; it is good that paren match gets confused, because that way you
  3008. ;; catch _all_ imbalances.
  3009. (defun viper-paren-match (arg)
  3010. "Go to the matching parenthesis."
  3011. (interactive "P")
  3012. (viper-leave-region-active)
  3013. (let ((com (viper-getcom arg))
  3014. (parse-sexp-ignore-comments viper-parse-sexp-ignore-comments)
  3015. anchor-point)
  3016. (if (integerp arg)
  3017. (if (or (> arg 99) (< arg 1))
  3018. (error "Prefix must be between 1 and 99")
  3019. (goto-char
  3020. (if (> (point-max) 80000)
  3021. (* (/ (point-max) 100) arg)
  3022. (/ (* (point-max) arg) 100)))
  3023. (back-to-indentation))
  3024. (let (beg-lim end-lim)
  3025. (if (and (eolp) (not (bolp))) (forward-char -1))
  3026. (if (not (looking-at "[][(){}]"))
  3027. (setq anchor-point (point)))
  3028. (setq beg-lim (point-at-bol)
  3029. end-lim (point-at-eol))
  3030. (cond ((re-search-forward "[][(){}]" end-lim t)
  3031. (backward-char) )
  3032. ((re-search-backward "[][(){}]" beg-lim t))
  3033. (t
  3034. (error "No matching character on line"))))
  3035. (cond ((looking-at "[([{]")
  3036. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3037. (forward-sexp 1)
  3038. (if com
  3039. (viper-execute-com 'viper-paren-match nil com)
  3040. (backward-char)))
  3041. (anchor-point
  3042. (if com
  3043. (progn
  3044. (viper-move-marker-locally 'viper-com-point anchor-point)
  3045. (forward-char 1)
  3046. (viper-execute-com 'viper-paren-match nil com)
  3047. )))
  3048. ((looking-at "[])}]")
  3049. (forward-char)
  3050. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3051. (backward-sexp 1)
  3052. (if com (viper-execute-com 'viper-paren-match nil com)))
  3053. (t (error "Viper bell"))))))
  3054. (defun viper-toggle-parse-sexp-ignore-comments ()
  3055. (interactive)
  3056. (setq viper-parse-sexp-ignore-comments
  3057. (not viper-parse-sexp-ignore-comments))
  3058. (princ (format-message
  3059. "From now on, `%%' will %signore parentheses inside comment fields"
  3060. (if viper-parse-sexp-ignore-comments "" "NOT "))))
  3061. ;; sentence, paragraph and heading
  3062. (defun viper-forward-sentence (arg)
  3063. "Forward sentence."
  3064. (interactive "P")
  3065. (or (eq last-command this-command)
  3066. (push-mark nil t))
  3067. (let ((val (viper-p-val arg))
  3068. (com (viper-getcom arg)))
  3069. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3070. (forward-sentence val)
  3071. (if com (viper-execute-com 'viper-forward-sentence nil com))))
  3072. (defun viper-backward-sentence (arg)
  3073. "Backward sentence."
  3074. (interactive "P")
  3075. (or (eq last-command this-command)
  3076. (push-mark nil t))
  3077. (let ((val (viper-p-val arg))
  3078. (com (viper-getcom arg)))
  3079. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3080. (backward-sentence val)
  3081. (if com (viper-execute-com 'viper-backward-sentence nil com))))
  3082. (defun viper-forward-paragraph (arg)
  3083. "Forward paragraph."
  3084. (interactive "P")
  3085. (or (eq last-command this-command)
  3086. (push-mark nil t))
  3087. (let ((val (viper-p-val arg))
  3088. ;; if you want d} operate on whole lines, change viper-getcom to
  3089. ;; viper-getCom below
  3090. (com (viper-getcom arg)))
  3091. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3092. (forward-paragraph val)
  3093. (if com
  3094. (progn
  3095. (backward-char 1)
  3096. (viper-execute-com 'viper-forward-paragraph nil com)))))
  3097. (defun viper-backward-paragraph (arg)
  3098. "Backward paragraph."
  3099. (interactive "P")
  3100. (or (eq last-command this-command)
  3101. (push-mark nil t))
  3102. (let ((val (viper-p-val arg))
  3103. ;; if you want d{ operate on whole lines, change viper-getcom to
  3104. ;; viper-getCom below
  3105. (com (viper-getcom arg)))
  3106. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3107. (backward-paragraph val)
  3108. (if com
  3109. (progn
  3110. (forward-char 1)
  3111. (viper-execute-com 'viper-backward-paragraph nil com)
  3112. (backward-char 1)))))
  3113. ;; should be mode-specific
  3114. (defun viper-prev-heading (arg)
  3115. (interactive "P")
  3116. (let ((val (viper-p-val arg))
  3117. (com (viper-getCom arg)))
  3118. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3119. (re-search-backward viper-heading-start nil t val)
  3120. (goto-char (match-beginning 0))
  3121. (if com (viper-execute-com 'viper-prev-heading nil com))))
  3122. (defun viper-heading-end (arg)
  3123. (interactive "P")
  3124. (let ((val (viper-p-val arg))
  3125. (com (viper-getCom arg)))
  3126. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3127. (re-search-forward viper-heading-end nil t val)
  3128. (goto-char (match-beginning 0))
  3129. (if com (viper-execute-com 'viper-heading-end nil com))))
  3130. (defun viper-next-heading (arg)
  3131. (interactive "P")
  3132. (let ((val (viper-p-val arg))
  3133. (com (viper-getCom arg)))
  3134. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3135. (end-of-line)
  3136. (re-search-forward viper-heading-start nil t val)
  3137. (goto-char (match-beginning 0))
  3138. (if com (viper-execute-com 'viper-next-heading nil com))))
  3139. ;; scrolling
  3140. (defun viper-scroll-screen (arg)
  3141. "Scroll to next screen."
  3142. (interactive "p")
  3143. (condition-case nil
  3144. (if (> arg 0)
  3145. (while (> arg 0)
  3146. (scroll-up)
  3147. (setq arg (1- arg)))
  3148. (while (> 0 arg)
  3149. (scroll-down)
  3150. (setq arg (1+ arg))))
  3151. (error (beep 1)
  3152. (if (> arg 0)
  3153. (progn
  3154. (message "End of buffer")
  3155. (goto-char (point-max)))
  3156. (message "Beginning of buffer")
  3157. (goto-char (point-min))))
  3158. ))
  3159. (defun viper-scroll-screen-back (arg)
  3160. "Scroll to previous screen."
  3161. (interactive "p")
  3162. (viper-scroll-screen (- arg)))
  3163. (defun viper-scroll-down (arg)
  3164. "Pull down half screen."
  3165. (interactive "P")
  3166. (condition-case nil
  3167. (if (null arg)
  3168. (scroll-down (/ (window-height) 2))
  3169. (scroll-down arg))
  3170. (error (beep 1)
  3171. (message "Beginning of buffer")
  3172. (goto-char (point-min)))))
  3173. (defun viper-scroll-down-one (arg)
  3174. "Scroll up one line."
  3175. (interactive "p")
  3176. (scroll-down arg))
  3177. (defun viper-scroll-up (arg)
  3178. "Pull up half screen."
  3179. (interactive "P")
  3180. (condition-case nil
  3181. (if (null arg)
  3182. (scroll-up (/ (window-height) 2))
  3183. (scroll-up arg))
  3184. (error (beep 1)
  3185. (message "End of buffer")
  3186. (goto-char (point-max)))))
  3187. (defun viper-scroll-up-one (arg)
  3188. "Scroll down one line."
  3189. (interactive "p")
  3190. (scroll-up arg))
  3191. ;; searching
  3192. (defun viper-insert-isearch-string ()
  3193. "Insert `isearch' last search string."
  3194. (interactive)
  3195. (when isearch-string (insert isearch-string)))
  3196. (defun viper-if-string (prompt)
  3197. (if (memq viper-intermediate-command
  3198. '(viper-command-argument viper-digit-argument viper-repeat))
  3199. (setq viper-this-command-keys (this-command-keys)))
  3200. (let* ((keymap (let ((keymap (copy-keymap minibuffer-local-map)))
  3201. (define-key keymap [(control ?s)] 'viper-insert-isearch-string)
  3202. keymap))
  3203. (s (viper-read-string-with-history
  3204. prompt
  3205. nil ; no initial
  3206. 'viper-search-history
  3207. (car viper-search-history)
  3208. keymap)))
  3209. (if (not (string= s ""))
  3210. (setq viper-s-string s))))
  3211. (defun viper-toggle-search-style (arg)
  3212. "Toggle the value of viper-case-fold-search/viper-re-search.
  3213. Without prefix argument, will ask which search style to toggle. With prefix
  3214. arg 1, toggles viper-case-fold-search; with arg 2 toggles viper-re-search.
  3215. Although this function is bound to \\[viper-toggle-search-style], the most
  3216. convenient way to use it is to bind `//' to the macro
  3217. `1 M-x viper-toggle-search-style' and `///' to
  3218. `2 M-x viper-toggle-search-style'. In this way, hitting `//' quickly will
  3219. toggle case-fold-search and hitting `/' three times with toggle regexp
  3220. search. Macros are more convenient in this case because they don't affect
  3221. the Emacs binding of `/'."
  3222. (interactive "P")
  3223. (let (msg)
  3224. (cond ((or (eq arg 1)
  3225. (and (null arg)
  3226. (y-or-n-p (format-message
  3227. "Search style: `%s'. Want `%s'? "
  3228. (if viper-case-fold-search
  3229. "case-insensitive" "case-sensitive")
  3230. (if viper-case-fold-search
  3231. "case-sensitive"
  3232. "case-insensitive")))))
  3233. (setq viper-case-fold-search (null viper-case-fold-search))
  3234. (if viper-case-fold-search
  3235. (setq msg "Search becomes case-insensitive")
  3236. (setq msg "Search becomes case-sensitive")))
  3237. ((or (eq arg 2)
  3238. (and (null arg)
  3239. (y-or-n-p (format-message
  3240. "Search style: `%s'. Want `%s'? "
  3241. (if viper-re-search
  3242. "regexp-search" "vanilla-search")
  3243. (if viper-re-search
  3244. "vanilla-search"
  3245. "regexp-search")))))
  3246. (setq viper-re-search (null viper-re-search))
  3247. (if viper-re-search
  3248. (setq msg "Search becomes regexp-style")
  3249. (setq msg "Search becomes vanilla-style")))
  3250. (t
  3251. (setq msg "Search style remains unchanged")))
  3252. (princ msg t)))
  3253. (defun viper-set-searchstyle-toggling-macros (unset &optional major-mode)
  3254. "Set the macros for toggling the search style in Viper's vi-state.
  3255. The macro that toggles case sensitivity is bound to `//', and the one that
  3256. toggles regexp search is bound to `///'.
  3257. With a prefix argument, this function unsets the macros.
  3258. If MAJOR-MODE is set, set the macros only in that major mode."
  3259. (interactive "P")
  3260. (let (scope)
  3261. (if (and major-mode (symbolp major-mode))
  3262. (setq scope major-mode)
  3263. (setq scope 't))
  3264. (or noninteractive
  3265. (if (not unset)
  3266. (progn
  3267. ;; toggle case sensitivity in search
  3268. (viper-record-kbd-macro
  3269. "//" 'vi-state
  3270. [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]
  3271. scope)
  3272. ;; toggle regexp/vanilla search
  3273. (viper-record-kbd-macro
  3274. "///" 'vi-state
  3275. [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]
  3276. scope)
  3277. (if (if (featurep 'xemacs)
  3278. (interactive-p)
  3279. (called-interactively-p 'interactive))
  3280. (message
  3281. "// and /// now toggle case-sensitivity and regexp search")))
  3282. (viper-unrecord-kbd-macro "//" 'vi-state)
  3283. (sit-for 2)
  3284. (viper-unrecord-kbd-macro "///" 'vi-state)))
  3285. ))
  3286. (defun viper-set-parsing-style-toggling-macro (unset)
  3287. "Set `%%%' to be a macro that toggles whether comment fields should be parsed for matching parentheses.
  3288. This is used in conjunction with the `%' command.
  3289. With a prefix argument, unsets the macro."
  3290. (interactive "P")
  3291. (or noninteractive
  3292. (if (not unset)
  3293. (progn
  3294. ;; Make %%% toggle parsing comments for matching parentheses
  3295. (viper-record-kbd-macro
  3296. "%%%" 'vi-state
  3297. [(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]
  3298. 't)
  3299. (if (if (featurep 'xemacs)
  3300. (interactive-p)
  3301. (called-interactively-p 'interactive))
  3302. (message
  3303. "%%%%%% now toggles whether comments should be parsed for matching parentheses")))
  3304. (viper-unrecord-kbd-macro "%%%" 'vi-state))))
  3305. (defun viper-set-emacs-state-searchstyle-macros (unset &optional arg-majormode)
  3306. "Set the macros for toggling the search style in Viper's emacs-state.
  3307. The macro that toggles case sensitivity is bound to `//', and the one that
  3308. toggles regexp search is bound to `///'.
  3309. With a prefix argument, this function unsets the macros.
  3310. If the optional prefix argument is non-nil and specifies a valid major mode,
  3311. this sets the macros only in the macros in that major mode. Otherwise,
  3312. the macros are set in the current major mode.
  3313. \(When unsetting the macros, the second argument has no effect.)"
  3314. (interactive "P")
  3315. (or noninteractive
  3316. (if (not unset)
  3317. (progn
  3318. ;; toggle case sensitivity in search
  3319. (viper-record-kbd-macro
  3320. "//" 'emacs-state
  3321. [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]
  3322. (or arg-majormode major-mode))
  3323. ;; toggle regexp/vanilla search
  3324. (viper-record-kbd-macro
  3325. "///" 'emacs-state
  3326. [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]
  3327. (or arg-majormode major-mode))
  3328. (if (if (featurep 'xemacs)
  3329. (interactive-p)
  3330. (called-interactively-p 'interactive))
  3331. (message
  3332. "// and /// now toggle case-sensitivity and regexp search.")))
  3333. (viper-unrecord-kbd-macro "//" 'emacs-state)
  3334. (sit-for 2)
  3335. (viper-unrecord-kbd-macro "///" 'emacs-state))))
  3336. (defun viper-search-forward (arg)
  3337. "Search a string forward.
  3338. ARG is used to find the ARG's occurrence of the string.
  3339. Null string will repeat previous search."
  3340. (interactive "P")
  3341. (let ((val (viper-P-val arg))
  3342. (com (viper-getcom arg))
  3343. (old-str viper-s-string)
  3344. debug-on-error)
  3345. (setq viper-s-forward t)
  3346. (viper-if-string "/")
  3347. ;; this is not used at present, but may be used later
  3348. (if (or (not (equal old-str viper-s-string))
  3349. (not (markerp viper-local-search-start-marker))
  3350. (not (marker-buffer viper-local-search-start-marker)))
  3351. (setq viper-local-search-start-marker (point-marker)))
  3352. (viper-search viper-s-string t val)
  3353. (if com
  3354. (progn
  3355. (viper-move-marker-locally 'viper-com-point (mark t))
  3356. (viper-execute-com 'viper-search-next val com)))
  3357. ))
  3358. (defun viper-search-backward (arg)
  3359. "Search a string backward.
  3360. ARG is used to find the ARG's occurrence of the string.
  3361. Null string will repeat previous search."
  3362. (interactive "P")
  3363. (let ((val (viper-P-val arg))
  3364. (com (viper-getcom arg))
  3365. (old-str viper-s-string)
  3366. debug-on-error)
  3367. (setq viper-s-forward nil)
  3368. (viper-if-string "?")
  3369. ;; this is not used at present, but may be used later
  3370. (if (or (not (equal old-str viper-s-string))
  3371. (not (markerp viper-local-search-start-marker))
  3372. (not (marker-buffer viper-local-search-start-marker)))
  3373. (setq viper-local-search-start-marker (point-marker)))
  3374. (viper-search viper-s-string nil val)
  3375. (if com
  3376. (progn
  3377. (viper-move-marker-locally 'viper-com-point (mark t))
  3378. (viper-execute-com 'viper-search-next val com)))))
  3379. ;; Search for COUNT's occurrence of STRING.
  3380. ;; Search is forward if FORWARD is non-nil, otherwise backward.
  3381. ;; INIT-POINT is the position where search is to start.
  3382. ;; Arguments:
  3383. ;; (STRING FORW COUNT &optional NO-OFFSET INIT-POINT LIMIT FAIL-IF-NOT-FOUND)
  3384. (defun viper-search (string forward arg
  3385. &optional no-offset init-point fail-if-not-found)
  3386. (if (not (equal string ""))
  3387. (let ((val (viper-p-val arg))
  3388. (com (viper-getcom arg))
  3389. (offset (not no-offset))
  3390. (case-fold-search viper-case-fold-search)
  3391. (start-point (or init-point (point))))
  3392. (viper-deactivate-mark)
  3393. (if forward
  3394. (condition-case nil
  3395. (progn
  3396. (if offset (viper-forward-char-carefully))
  3397. (if viper-re-search
  3398. (progn
  3399. (re-search-forward string nil nil val)
  3400. (re-search-backward string))
  3401. (search-forward string nil nil val)
  3402. (search-backward string))
  3403. (if (not (equal start-point (point)))
  3404. (push-mark start-point t)))
  3405. (search-failed
  3406. (if (and (not fail-if-not-found) viper-search-wrap-around)
  3407. (progn
  3408. (message "Search wrapped around BOTTOM of buffer")
  3409. (goto-char (point-min))
  3410. (viper-search string forward (cons 1 com) t start-point 'fail)
  3411. ;; don't wait in macros
  3412. (or executing-kbd-macro
  3413. (memq viper-intermediate-command
  3414. '(viper-repeat
  3415. viper-digit-argument
  3416. viper-command-argument))
  3417. (sit-for 2))
  3418. ;; delete the wrap-around message
  3419. (message "")
  3420. )
  3421. (goto-char start-point)
  3422. (error "`%s': %s not found"
  3423. string
  3424. (if viper-re-search "Pattern" "String"))
  3425. )))
  3426. ;; backward
  3427. (condition-case nil
  3428. (progn
  3429. (if viper-re-search
  3430. (re-search-backward string nil nil val)
  3431. (search-backward string nil nil val))
  3432. (if (not (equal start-point (point)))
  3433. (push-mark start-point t)))
  3434. (search-failed
  3435. (if (and (not fail-if-not-found) viper-search-wrap-around)
  3436. (progn
  3437. (message "Search wrapped around TOP of buffer")
  3438. (goto-char (point-max))
  3439. (viper-search string forward (cons 1 com) t start-point 'fail)
  3440. ;; don't wait in macros
  3441. (or executing-kbd-macro
  3442. (memq viper-intermediate-command
  3443. '(viper-repeat
  3444. viper-digit-argument
  3445. viper-command-argument))
  3446. (sit-for 2))
  3447. ;; delete the wrap-around message
  3448. (message "")
  3449. )
  3450. (goto-char start-point)
  3451. (error "`%s': %s not found"
  3452. string
  3453. (if viper-re-search "Pattern" "String"))
  3454. ))))
  3455. ;; pull up or down if at top/bottom of window
  3456. (viper-adjust-window)
  3457. ;; highlight the result of search
  3458. ;; don't wait and don't highlight in macros
  3459. (or executing-kbd-macro
  3460. (memq viper-intermediate-command
  3461. '(viper-repeat viper-digit-argument viper-command-argument))
  3462. (viper-flash-search-pattern))
  3463. )))
  3464. (defun viper-search-next (arg)
  3465. "Repeat previous search."
  3466. (interactive "P")
  3467. (let ((val (viper-p-val arg))
  3468. (com (viper-getcom arg))
  3469. debug-on-error)
  3470. (if (or (null viper-s-string) (string= viper-s-string ""))
  3471. (error viper-NoPrevSearch))
  3472. (viper-search viper-s-string viper-s-forward arg)
  3473. (if com
  3474. (progn
  3475. (viper-move-marker-locally 'viper-com-point (mark t))
  3476. (viper-execute-com 'viper-search-next val com)))))
  3477. (defun viper-search-Next (arg)
  3478. "Repeat previous search in the reverse direction."
  3479. (interactive "P")
  3480. (let ((val (viper-p-val arg))
  3481. (com (viper-getcom arg))
  3482. debug-on-error)
  3483. (if (null viper-s-string) (error viper-NoPrevSearch))
  3484. (viper-search viper-s-string (not viper-s-forward) arg)
  3485. (if com
  3486. (progn
  3487. (viper-move-marker-locally 'viper-com-point (mark t))
  3488. (viper-execute-com 'viper-search-Next val com)))))
  3489. ;; Search contents of buffer defined by one of Viper's motion commands.
  3490. ;; Repeatable via `n' and `N'.
  3491. (defun viper-buffer-search-enable (&optional c)
  3492. (cond (c (setq viper-buffer-search-char c))
  3493. ((null viper-buffer-search-char)
  3494. ;; ?g acts as a default value for viper-buffer-search-char
  3495. (setq viper-buffer-search-char ?g)))
  3496. (define-key viper-vi-basic-map
  3497. (cond ((viper-characterp viper-buffer-search-char)
  3498. (char-to-string viper-buffer-search-char))
  3499. (t (error "viper-buffer-search-char: wrong value type, %S"
  3500. viper-buffer-search-char)))
  3501. 'viper-command-argument)
  3502. (aset viper-exec-array viper-buffer-search-char 'viper-exec-buffer-search)
  3503. (setq viper-prefix-commands
  3504. (cons viper-buffer-search-char viper-prefix-commands)))
  3505. ;; This is a Viper wrapper for isearch-forward.
  3506. (defun viper-isearch-forward (arg)
  3507. "Do incremental search forward."
  3508. (interactive "P")
  3509. ;; emacs bug workaround
  3510. (if (listp arg) (setq arg (car arg)))
  3511. (viper-exec-form-in-emacs (list 'isearch-forward arg)))
  3512. ;; This is a Viper wrapper for isearch-backward."
  3513. (defun viper-isearch-backward (arg)
  3514. "Do incremental search backward."
  3515. (interactive "P")
  3516. ;; emacs bug workaround
  3517. (if (listp arg) (setq arg (car arg)))
  3518. (viper-exec-form-in-emacs (list 'isearch-backward arg)))
  3519. ;; visiting and killing files, buffers
  3520. (defun viper-switch-to-buffer ()
  3521. "Switch to buffer in the current window."
  3522. (interactive)
  3523. (let ((other-buffer (other-buffer (current-buffer)))
  3524. buffer)
  3525. (setq buffer
  3526. (funcall viper-read-buffer-function
  3527. "Switch to buffer in this window: " other-buffer))
  3528. (switch-to-buffer buffer)))
  3529. (defun viper-switch-to-buffer-other-window ()
  3530. "Switch to buffer in another window."
  3531. (interactive)
  3532. (let ((other-buffer (other-buffer (current-buffer)))
  3533. buffer)
  3534. (setq buffer
  3535. (funcall viper-read-buffer-function
  3536. "Switch to buffer in another window: " other-buffer))
  3537. (switch-to-buffer-other-window buffer)))
  3538. (defun viper-kill-buffer ()
  3539. "Kill a buffer."
  3540. (interactive)
  3541. (let (buffer buffer-name)
  3542. (setq buffer-name
  3543. (funcall viper-read-buffer-function
  3544. (format "Kill buffer (%s): "
  3545. (buffer-name (current-buffer)))))
  3546. (setq buffer
  3547. (if (null buffer-name)
  3548. (current-buffer)
  3549. (get-buffer buffer-name)))
  3550. (if (null buffer) (error "`%s': No such buffer" buffer-name))
  3551. (if (or (not (buffer-modified-p buffer))
  3552. (y-or-n-p
  3553. (format-message
  3554. "Buffer `%s' is modified, are you sure you want to kill it? "
  3555. buffer-name)))
  3556. (kill-buffer buffer)
  3557. (error "Buffer not killed"))))
  3558. ;; yank and pop
  3559. (defsubst viper-yank (text)
  3560. "Yank TEXT silently. This works correctly with Emacs's yank-pop command."
  3561. (insert text)
  3562. (setq this-command 'yank))
  3563. (defun viper-put-back (arg)
  3564. "Put back after point/below line."
  3565. (interactive "P")
  3566. (let ((val (viper-p-val arg))
  3567. (text (if viper-use-register
  3568. (cond ((viper-valid-register viper-use-register '(digit))
  3569. (current-kill
  3570. (- viper-use-register ?1) 'do-not-rotate))
  3571. ((viper-valid-register viper-use-register)
  3572. (get-register (downcase viper-use-register)))
  3573. (t (error viper-InvalidRegister viper-use-register)))
  3574. (current-kill 0)))
  3575. sv-point chars-inserted lines-inserted)
  3576. (if (null text)
  3577. (if viper-use-register
  3578. (let ((reg viper-use-register))
  3579. (setq viper-use-register nil)
  3580. (error viper-EmptyRegister reg))
  3581. (error "Viper bell")))
  3582. (setq viper-use-register nil)
  3583. (if (viper-end-with-a-newline-p text)
  3584. (progn
  3585. (end-of-line)
  3586. (if (eobp)
  3587. (insert "\n")
  3588. (forward-line 1))
  3589. (beginning-of-line))
  3590. (if (not (eolp)) (viper-forward-char-carefully)))
  3591. (set-marker (viper-mark-marker) (point) (current-buffer))
  3592. (viper-set-destructive-command
  3593. (list 'viper-put-back val nil viper-use-register nil nil))
  3594. (setq sv-point (point))
  3595. (viper-loop val (viper-yank text))
  3596. (setq chars-inserted (abs (- (point) sv-point))
  3597. lines-inserted (abs (count-lines (point) sv-point)))
  3598. (if (or (> chars-inserted viper-change-notification-threshold)
  3599. (> lines-inserted viper-change-notification-threshold))
  3600. (unless (viper-is-in-minibuffer)
  3601. (message "Inserted %d character(s), %d line(s)"
  3602. chars-inserted lines-inserted))))
  3603. ;; Vi puts cursor on the last char when the yanked text doesn't contain a
  3604. ;; newline; it leaves the cursor at the beginning when the text contains
  3605. ;; a newline
  3606. (if (viper-same-line (point) (mark))
  3607. (or (= (point) (mark)) (viper-backward-char-carefully))
  3608. (exchange-point-and-mark)
  3609. (if (bolp)
  3610. (back-to-indentation)))
  3611. (viper-deactivate-mark))
  3612. (defun viper-Put-back (arg)
  3613. "Put back at point/above line."
  3614. (interactive "P")
  3615. (let ((val (viper-p-val arg))
  3616. (text (if viper-use-register
  3617. (cond ((viper-valid-register viper-use-register '(digit))
  3618. (current-kill
  3619. (- viper-use-register ?1) 'do-not-rotate))
  3620. ((viper-valid-register viper-use-register)
  3621. (get-register (downcase viper-use-register)))
  3622. (t (error viper-InvalidRegister viper-use-register)))
  3623. (current-kill 0)))
  3624. sv-point chars-inserted lines-inserted)
  3625. (if (null text)
  3626. (if viper-use-register
  3627. (let ((reg viper-use-register))
  3628. (setq viper-use-register nil)
  3629. (error viper-EmptyRegister reg))
  3630. (error "Viper bell")))
  3631. (setq viper-use-register nil)
  3632. (if (viper-end-with-a-newline-p text) (beginning-of-line))
  3633. (viper-set-destructive-command
  3634. (list 'viper-Put-back val nil viper-use-register nil nil))
  3635. (set-marker (viper-mark-marker) (point) (current-buffer))
  3636. (setq sv-point (point))
  3637. (viper-loop val (viper-yank text))
  3638. (setq chars-inserted (abs (- (point) sv-point))
  3639. lines-inserted (abs (count-lines (point) sv-point)))
  3640. (if (or (> chars-inserted viper-change-notification-threshold)
  3641. (> lines-inserted viper-change-notification-threshold))
  3642. (unless (viper-is-in-minibuffer)
  3643. (message "Inserted %d character(s), %d line(s)"
  3644. chars-inserted lines-inserted))))
  3645. ;; Vi puts cursor on the last char when the yanked text doesn't contain a
  3646. ;; newline; it leaves the cursor at the beginning when the text contains
  3647. ;; a newline
  3648. (if (viper-same-line (point) (mark))
  3649. (or (= (point) (mark)) (viper-backward-char-carefully))
  3650. (exchange-point-and-mark)
  3651. (if (bolp)
  3652. (back-to-indentation)))
  3653. (viper-deactivate-mark))
  3654. ;; Copy region to kill-ring.
  3655. ;; If BEG and END do not belong to the same buffer, copy empty region.
  3656. (defun viper-copy-region-as-kill (beg end)
  3657. (condition-case nil
  3658. (copy-region-as-kill beg end)
  3659. (error (copy-region-as-kill beg beg))))
  3660. (defun viper-delete-char (arg)
  3661. "Delete next character."
  3662. (interactive "P")
  3663. (let ((val (viper-p-val arg))
  3664. end-del-pos)
  3665. (viper-set-destructive-command
  3666. (list 'viper-delete-char val nil nil nil nil))
  3667. (if (and viper-ex-style-editing
  3668. (> val (viper-chars-in-region (point) (viper-line-pos 'end))))
  3669. (setq val (viper-chars-in-region (point) (viper-line-pos 'end))))
  3670. (if (and viper-ex-style-motion (eolp))
  3671. (if (bolp) (error "Viper bell") (setq val 0))) ; not bol---simply back 1 ch
  3672. (save-excursion
  3673. (viper-forward-char-carefully val)
  3674. (setq end-del-pos (point)))
  3675. (if viper-use-register
  3676. (progn
  3677. (cond ((viper-valid-register viper-use-register '((Letter)))
  3678. (viper-append-to-register
  3679. (downcase viper-use-register) (point) end-del-pos))
  3680. ((viper-valid-register viper-use-register)
  3681. (copy-to-register
  3682. viper-use-register (point) end-del-pos nil))
  3683. (t (error viper-InvalidRegister viper-use-register)))
  3684. (setq viper-use-register nil)))
  3685. (delete-char val t)
  3686. (if viper-ex-style-motion
  3687. (if (and (eolp) (not (bolp))) (backward-char 1)))
  3688. ))
  3689. (defun viper-delete-backward-char (arg)
  3690. "Delete previous character. On reaching beginning of line, stop and beep."
  3691. (interactive "P")
  3692. (let ((val (viper-p-val arg))
  3693. end-del-pos)
  3694. (viper-set-destructive-command
  3695. (list 'viper-delete-backward-char val nil nil nil nil))
  3696. (if (and
  3697. viper-ex-style-editing
  3698. (> val (viper-chars-in-region (viper-line-pos 'start) (point))))
  3699. (setq val (viper-chars-in-region (viper-line-pos 'start) (point))))
  3700. (save-excursion
  3701. (viper-backward-char-carefully val)
  3702. (setq end-del-pos (point)))
  3703. (if viper-use-register
  3704. (progn
  3705. (cond ((viper-valid-register viper-use-register '(Letter))
  3706. (viper-append-to-register
  3707. (downcase viper-use-register) end-del-pos (point)))
  3708. ((viper-valid-register viper-use-register)
  3709. (copy-to-register
  3710. viper-use-register end-del-pos (point) nil))
  3711. (t (error viper-InvalidRegister viper-use-register)))
  3712. (setq viper-use-register nil)))
  3713. (if (and (bolp) viper-ex-style-editing)
  3714. (ding))
  3715. (delete-char (- val) t)))
  3716. (defun viper-del-backward-char-in-insert ()
  3717. "Delete 1 char backwards while in insert mode."
  3718. (interactive)
  3719. (if (and viper-ex-style-editing (bolp))
  3720. (beep 1)
  3721. ;; don't put on kill ring
  3722. (delete-char -1 nil)))
  3723. (defun viper-del-backward-char-in-replace ()
  3724. "Delete one character in replace mode.
  3725. If `viper-delete-backwards-in-replace' is t, then DEL key actually deletes
  3726. characters. If it is nil, then the cursor just moves backwards, similarly
  3727. to Vi. The variable `viper-ex-style-editing', if t, doesn't let the
  3728. cursor move past the beginning of line."
  3729. (interactive)
  3730. (cond (viper-delete-backwards-in-replace
  3731. (cond ((not (bolp))
  3732. ;; don't put on kill ring
  3733. (delete-char -1 nil))
  3734. (viper-ex-style-editing
  3735. (beep 1))
  3736. ((bobp)
  3737. (beep 1))
  3738. (t
  3739. ;; don't put on kill ring
  3740. (delete-char -1 nil))))
  3741. (viper-ex-style-editing
  3742. (if (bolp)
  3743. (beep 1)
  3744. (backward-char 1)))
  3745. (t
  3746. (backward-char 1))))
  3747. (defun viper-del-forward-char-in-insert ()
  3748. "Delete 1 char forward if in insert or replace state."
  3749. (interactive)
  3750. ;; don't put on kill ring
  3751. (delete-char 1 nil))
  3752. ;; join lines.
  3753. (defun viper-join-lines (arg)
  3754. "Join this line to next, if ARG is nil. Otherwise, join ARG lines."
  3755. (interactive "*P")
  3756. (let ((val (viper-P-val arg)))
  3757. (viper-set-destructive-command
  3758. (list 'viper-join-lines val nil nil nil nil))
  3759. (viper-loop (if (null val) 1 (1- val))
  3760. (end-of-line)
  3761. (if (not (eobp))
  3762. (progn
  3763. (forward-line 1)
  3764. (delete-region (point) (1- (point)))
  3765. (fixup-whitespace)
  3766. ;; fixup-whitespace sometimes does not leave space
  3767. ;; between objects, so we insert it as in Vi
  3768. (or (looking-at " ")
  3769. (insert " ")
  3770. (backward-char 1))
  3771. )))))
  3772. ;; Replace state
  3773. (defun viper-change (beg end)
  3774. (if (markerp beg) (setq beg (marker-position beg)))
  3775. (if (markerp end) (setq end (marker-position end)))
  3776. ;; beg is sometimes (mark t), which may be nil
  3777. (or beg (setq beg end))
  3778. (viper-set-complex-command-for-undo)
  3779. (if viper-use-register
  3780. (progn
  3781. (copy-to-register viper-use-register beg end nil)
  3782. (setq viper-use-register nil)))
  3783. (viper-set-replace-overlay beg end)
  3784. (setq last-command nil) ; separate repl text from prev kills
  3785. (if (= (viper-replace-start) (point-max))
  3786. (error "End of buffer"))
  3787. (setq viper-last-replace-region
  3788. (buffer-substring (viper-replace-start)
  3789. (viper-replace-end)))
  3790. ;; protect against error while inserting "@" and other disasters
  3791. ;; (e.g., read-only buff)
  3792. (condition-case conds
  3793. (if (or viper-allow-multiline-replace-regions
  3794. (viper-same-line (viper-replace-start)
  3795. (viper-replace-end)))
  3796. (progn
  3797. ;; tabs cause problems in replace, so untabify
  3798. (goto-char (viper-replace-end))
  3799. (insert-before-markers "@") ; put placeholder after the TAB
  3800. (untabify (viper-replace-start) (point))
  3801. ;; del @, don't put on kill ring
  3802. (delete-char -1)
  3803. (viper-set-replace-overlay-glyphs
  3804. viper-replace-region-start-delimiter
  3805. viper-replace-region-end-delimiter)
  3806. ;; this move takes care of the last posn in the overlay, which
  3807. ;; has to be shifted because of insert. We can't simply insert
  3808. ;; "$" before-markers because then overlay-start will shift the
  3809. ;; beginning of the overlay in case we are replacing a single
  3810. ;; character. This fixes the bug with `s' and `cl' commands.
  3811. (viper-move-replace-overlay (viper-replace-start) (point))
  3812. (goto-char (viper-replace-start))
  3813. (viper-change-state-to-replace t))
  3814. (kill-region (viper-replace-start)
  3815. (viper-replace-end))
  3816. (viper-hide-replace-overlay)
  3817. (viper-change-state-to-insert))
  3818. (error ;; make sure that the overlay doesn't stay.
  3819. ;; go back to the original point
  3820. (goto-char (viper-replace-start))
  3821. (viper-hide-replace-overlay)
  3822. (viper-message-conditions conds))))
  3823. (defun viper-change-subr (beg end)
  3824. ;; beg is sometimes (mark t), which may be nil
  3825. (or beg (setq beg end))
  3826. (if viper-use-register
  3827. (progn
  3828. (copy-to-register viper-use-register beg end nil)
  3829. (setq viper-use-register nil)))
  3830. (kill-region beg end)
  3831. (setq this-command 'viper-change)
  3832. (viper-yank-last-insertion))
  3833. (defun viper-toggle-case (arg)
  3834. "Toggle character case."
  3835. (interactive "P")
  3836. (let ((val (viper-p-val arg)) (c))
  3837. (viper-set-destructive-command
  3838. (list 'viper-toggle-case val nil nil nil nil))
  3839. (while (> val 0)
  3840. (setq c (following-char))
  3841. (delete-char 1 nil)
  3842. (if (eq c (upcase c))
  3843. (insert-char (downcase c) 1)
  3844. (insert-char (upcase c) 1))
  3845. (if (eolp) (backward-char 1))
  3846. (setq val (1- val)))))
  3847. ;; query replace
  3848. (defun viper-query-replace ()
  3849. "Query replace.
  3850. If a null string is supplied as the string to be replaced,
  3851. the query replace mode will toggle between string replace
  3852. and regexp replace."
  3853. (interactive)
  3854. (let (str)
  3855. (setq str (viper-read-string-with-history
  3856. (if viper-re-query-replace "Query replace regexp: "
  3857. "Query replace: ")
  3858. nil ; no initial
  3859. 'viper-replace1-history
  3860. (car viper-replace1-history) ; default
  3861. ))
  3862. (if (string= str "")
  3863. (progn
  3864. (setq viper-re-query-replace (not viper-re-query-replace))
  3865. (message "Query replace mode changed to %s"
  3866. (if viper-re-query-replace "regexp replace"
  3867. "string replace")))
  3868. (if viper-re-query-replace
  3869. (query-replace-regexp
  3870. str
  3871. (viper-read-string-with-history
  3872. (format-message "Query replace regexp `%s' with: " str)
  3873. nil ; no initial
  3874. 'viper-replace1-history
  3875. (car viper-replace1-history) ; default
  3876. ))
  3877. (query-replace
  3878. str
  3879. (viper-read-string-with-history
  3880. (format-message "Query replace `%s' with: " str)
  3881. nil ; no initial
  3882. 'viper-replace1-history
  3883. (car viper-replace1-history) ; default
  3884. ))))))
  3885. ;; marking
  3886. (defun viper-mark-beginning-of-buffer ()
  3887. "Mark beginning of buffer."
  3888. (interactive)
  3889. (push-mark (point))
  3890. (goto-char (point-min))
  3891. (exchange-point-and-mark)
  3892. (message "Mark set at the beginning of buffer"))
  3893. (defun viper-mark-end-of-buffer ()
  3894. "Mark end of buffer."
  3895. (interactive)
  3896. (push-mark (point))
  3897. (goto-char (point-max))
  3898. (exchange-point-and-mark)
  3899. (message "Mark set at the end of buffer"))
  3900. (defun viper-mark-point ()
  3901. "Set mark at point of buffer."
  3902. (interactive)
  3903. (let ((char (read-char)))
  3904. (cond ((and (<= ?a char) (<= char ?z))
  3905. (point-to-register (viper-int-to-char (1+ (- char ?a)))))
  3906. ((viper= char ?<) (viper-mark-beginning-of-buffer))
  3907. ((viper= char ?>) (viper-mark-end-of-buffer))
  3908. ((viper= char ?.) (viper-set-mark-if-necessary))
  3909. ((viper= char ?,) (viper-cycle-through-mark-ring))
  3910. ((viper= char ?^) (push-mark viper-saved-mark t t))
  3911. ((viper= char ?D) (mark-defun))
  3912. (t (error "Viper bell"))
  3913. )))
  3914. ;; Algorithm: If first invocation of this command save mark on ring, goto
  3915. ;; mark, M0, and pop the most recent elt from the mark ring into mark,
  3916. ;; making it into the new mark, M1.
  3917. ;; Push this mark back and set mark to the original point position, p1.
  3918. ;; So, if you hit '' or `` then you can return to p1.
  3919. ;;
  3920. ;; If repeated command, pop top elt from the ring into mark and
  3921. ;; jump there. This forgets the position, p1, and puts M1 back into mark.
  3922. ;; Then we save the current pos, which is M0, jump to M1 and pop M2 from
  3923. ;; the ring into mark. Push M2 back on the ring and set mark to M0.
  3924. ;; etc.
  3925. (defun viper-cycle-through-mark-ring ()
  3926. "Visit previous locations on the mark ring.
  3927. One can use \\=`\\=` and \\='\\=' to temporarily jump 1 step back."
  3928. (let* ((sv-pt (point)))
  3929. ;; if repeated `m,' command, pop the previously saved mark.
  3930. ;; Prev saved mark is actually prev saved point. It is used if the
  3931. ;; user types `` or '' and is discarded
  3932. ;; from the mark ring by the next `m,' command.
  3933. ;; In any case, go to the previous or previously saved mark.
  3934. ;; Then push the current mark (popped off the ring) and set current
  3935. ;; point to be the mark. Current pt as mark is discarded by the next
  3936. ;; m, command.
  3937. (if (eq last-command 'viper-cycle-through-mark-ring)
  3938. ()
  3939. ;; save current mark if the first iteration
  3940. (setq mark-ring (delete (viper-mark-marker) mark-ring))
  3941. (if (mark t)
  3942. (push-mark (mark t) t)) )
  3943. (pop-mark)
  3944. (set-mark-command 1)
  3945. ;; don't duplicate mark on the ring
  3946. (setq mark-ring (delete (viper-mark-marker) mark-ring))
  3947. (push-mark sv-pt t)
  3948. (viper-deactivate-mark)
  3949. (setq this-command 'viper-cycle-through-mark-ring)
  3950. ))
  3951. (defun viper-goto-mark (arg)
  3952. "Go to mark."
  3953. (interactive "P")
  3954. (let ((char (read-char))
  3955. (com (viper-getcom arg)))
  3956. (viper-goto-mark-subr char com nil)))
  3957. (defun viper-goto-mark-and-skip-white (arg)
  3958. "Go to mark and skip to first non-white character on line."
  3959. (interactive "P")
  3960. (let ((char (read-char))
  3961. (com (viper-getCom arg)))
  3962. (viper-goto-mark-subr char com t)))
  3963. (defun viper-goto-mark-subr (char com skip-white)
  3964. (if (eobp)
  3965. (if (bobp)
  3966. (error "Empty buffer")
  3967. (backward-char 1)))
  3968. (cond ((viper-valid-register char '(letter))
  3969. (let* ((buff (current-buffer))
  3970. (reg (viper-int-to-char (1+ (- char ?a))))
  3971. (text-marker (get-register reg)))
  3972. ;; If marker points to file that had markers set (and those markers
  3973. ;; were saved (as e.g., in session.el), then restore those markers
  3974. (if (and (consp text-marker)
  3975. (eq (car text-marker) 'file-query)
  3976. (or (find-buffer-visiting (nth 1 text-marker))
  3977. (y-or-n-p (format "Visit file %s again? "
  3978. (nth 1 text-marker)))))
  3979. (save-excursion
  3980. (find-file (nth 1 text-marker))
  3981. (when (and (<= (nth 2 text-marker) (point-max))
  3982. (<= (point-min) (nth 2 text-marker)))
  3983. (setq text-marker (copy-marker (nth 2 text-marker)))
  3984. (set-register reg text-marker))))
  3985. (if com (viper-move-marker-locally 'viper-com-point (point)))
  3986. (if (not (viper-valid-marker text-marker))
  3987. (error viper-EmptyTextmarker char))
  3988. (if (and (viper-same-line (point) viper-last-jump)
  3989. (= (point) viper-last-jump-ignore))
  3990. (push-mark viper-last-jump t)
  3991. (push-mark nil t)) ; no msg
  3992. (viper-register-to-point reg)
  3993. (setq viper-last-jump (point-marker))
  3994. (cond (skip-white
  3995. (back-to-indentation)
  3996. (setq viper-last-jump-ignore (point))))
  3997. (if com
  3998. (if (equal buff (current-buffer))
  3999. (viper-execute-com (if skip-white
  4000. 'viper-goto-mark-and-skip-white
  4001. 'viper-goto-mark)
  4002. nil com)
  4003. (switch-to-buffer buff)
  4004. (goto-char viper-com-point)
  4005. (viper-change-state-to-vi)
  4006. (error "Viper bell")))))
  4007. ((and (not skip-white) (viper= char ?`))
  4008. (if com (viper-move-marker-locally 'viper-com-point (point)))
  4009. (if (and (viper-same-line (point) viper-last-jump)
  4010. (= (point) viper-last-jump-ignore))
  4011. (goto-char viper-last-jump))
  4012. (if (null (mark t)) (error "Mark is not set in this buffer"))
  4013. (if (= (point) (mark t)) (pop-mark))
  4014. (exchange-point-and-mark)
  4015. (setq viper-last-jump (point-marker)
  4016. viper-last-jump-ignore 0)
  4017. (if com (viper-execute-com 'viper-goto-mark nil com)))
  4018. ((and skip-white (viper= char ?'))
  4019. (if com (viper-move-marker-locally 'viper-com-point (point)))
  4020. (if (and (viper-same-line (point) viper-last-jump)
  4021. (= (point) viper-last-jump-ignore))
  4022. (goto-char viper-last-jump))
  4023. (if (= (point) (mark t)) (pop-mark))
  4024. (exchange-point-and-mark)
  4025. (setq viper-last-jump (point))
  4026. (back-to-indentation)
  4027. (setq viper-last-jump-ignore (point))
  4028. (if com (viper-execute-com 'viper-goto-mark-and-skip-white nil com)))
  4029. (t (error viper-InvalidTextmarker char))))
  4030. (defun viper-insert-tab ()
  4031. (interactive)
  4032. (insert-tab))
  4033. (defun viper-exchange-point-and-mark ()
  4034. (interactive)
  4035. (exchange-point-and-mark)
  4036. (back-to-indentation))
  4037. ;; Input Mode Indentation
  4038. (define-obsolete-function-alias 'viper-looking-back 'looking-back "24.4")
  4039. (defun viper-forward-indent ()
  4040. "Indent forward -- `C-t' in Vi."
  4041. (interactive)
  4042. (setq viper-cted t)
  4043. (indent-to (+ (current-column) viper-shift-width)))
  4044. (defun viper-backward-indent ()
  4045. "Backtab, `C-d' in Vi."
  4046. (interactive)
  4047. (if viper-cted
  4048. (let ((p (point)) (c (current-column)) bol (indent t))
  4049. (if (looking-back "[0^]" (1- (point)))
  4050. (progn
  4051. (if (eq ?^ (preceding-char))
  4052. (setq viper-preserve-indent t))
  4053. (delete-char -1)
  4054. (setq p (point))
  4055. (setq indent nil)))
  4056. (setq bol (point-at-bol))
  4057. (if (re-search-backward "[^ \t]" bol 1) (forward-char))
  4058. (delete-region (point) p)
  4059. (if indent
  4060. (indent-to (- c viper-shift-width)))
  4061. (if (or (bolp) (looking-back "[^ \t]" (1- (point))))
  4062. (setq viper-cted nil)))))
  4063. ;; do smart indent
  4064. (defun viper-indent-line (col)
  4065. (if viper-auto-indent
  4066. (progn
  4067. (setq viper-cted t)
  4068. (if (and viper-electric-mode
  4069. (not (memq major-mode '(fundamental-mode
  4070. text-mode
  4071. paragraph-indent-text-mode))))
  4072. (indent-according-to-mode)
  4073. (indent-to col)))))
  4074. (defun viper-autoindent ()
  4075. "Auto Indentation, Vi-style."
  4076. (interactive)
  4077. (let ((col (current-indentation)))
  4078. (if abbrev-mode (expand-abbrev))
  4079. (if viper-preserve-indent
  4080. (setq viper-preserve-indent nil)
  4081. (setq viper-current-indent col))
  4082. ;; don't leave whitespace lines around
  4083. (if (memq last-command
  4084. '(viper-autoindent
  4085. viper-open-line viper-Open-line
  4086. viper-replace-state-exit-cmd))
  4087. (indent-to-left-margin))
  4088. ;; use \n instead of newline, or else <Return> will move the insert point
  4089. ;;(newline 1)
  4090. (insert "\n")
  4091. (viper-indent-line viper-current-indent)
  4092. ))
  4093. ;; Viewing registers
  4094. (defun viper-ket-function (arg)
  4095. "Function called by ], the ket. View registers and call ]]."
  4096. (interactive "P")
  4097. (let ((reg (read-char)))
  4098. (cond ((viper-valid-register reg '(letter Letter))
  4099. (view-register (downcase reg)))
  4100. ((viper-valid-register reg '(digit))
  4101. (let ((text (current-kill (- reg ?1) 'do-not-rotate)))
  4102. (with-output-to-temp-buffer " *viper-info*"
  4103. (princ (format "Register %c contains the string:\n" reg))
  4104. (princ text))
  4105. ))
  4106. ((viper= ?\] reg)
  4107. (viper-next-heading arg))
  4108. (t (error
  4109. viper-InvalidRegister reg)))))
  4110. (defun viper-brac-function (arg)
  4111. "Function called by [, the brac. View textmarkers and call [[."
  4112. (interactive "P")
  4113. (let ((reg (read-char)))
  4114. (cond ((viper= ?\[ reg)
  4115. (viper-prev-heading arg))
  4116. ((viper= ?\] reg)
  4117. (viper-heading-end arg))
  4118. ((viper-valid-register reg '(letter))
  4119. (let* ((val (get-register (viper-int-to-char (1+ (- reg ?a)))))
  4120. (buf (if (not (markerp val))
  4121. (error viper-EmptyTextmarker reg)
  4122. (marker-buffer val)))
  4123. (pos (marker-position val))
  4124. line-no text (s pos) (e pos))
  4125. (with-output-to-temp-buffer " *viper-info*"
  4126. (if (and buf pos)
  4127. (progn
  4128. (with-current-buffer buf
  4129. (setq line-no (1+ (count-lines (point-min) val)))
  4130. (goto-char pos)
  4131. (beginning-of-line)
  4132. (if (re-search-backward "[^ \t]" nil t)
  4133. (setq s (point-at-bol)))
  4134. (goto-char pos)
  4135. (forward-line 1)
  4136. (if (re-search-forward "[^ \t]" nil t)
  4137. (progn
  4138. (end-of-line)
  4139. (setq e (point))))
  4140. (setq text (buffer-substring s e))
  4141. (setq text (format "%s<%c>%s"
  4142. (substring text 0 (- pos s))
  4143. reg (substring text (- pos s)))))
  4144. (princ
  4145. (format-message
  4146. "Textmarker `%c' is in buffer `%s' at line %d.\n"
  4147. reg (buffer-name buf) line-no))
  4148. (princ (format "Here is some text around %c:\n\n %s"
  4149. reg text)))
  4150. (princ (format-message viper-EmptyTextmarker reg))))
  4151. ))
  4152. (t (error viper-InvalidTextmarker reg)))))
  4153. (defun viper-delete-backward-word (arg)
  4154. "Delete previous word."
  4155. (interactive "p")
  4156. (save-excursion
  4157. (push-mark nil t)
  4158. (backward-word arg)
  4159. (delete-region (point) (mark t))
  4160. (pop-mark)))
  4161. ;; Get viper standard value of SYMBOL. If symbol is customized, get its
  4162. ;; standard value. Otherwise, get the value saved in the alist STORAGE. If
  4163. ;; STORAGE is nil, use viper-saved-user-settings.
  4164. (defun viper-standard-value (symbol &optional storage)
  4165. (or (eval (car (get symbol 'customized-value)))
  4166. (eval (car (get symbol 'saved-value)))
  4167. (nth 1 (assoc symbol (or storage viper-saved-user-settings)))))
  4168. (defun viper-set-expert-level (&optional dont-change-unless)
  4169. "Sets the expert level for a Viper user.
  4170. Can be called interactively to change (temporarily or permanently) the
  4171. current expert level.
  4172. The optional argument DONT-CHANGE-UNLESS, if not nil, says that
  4173. the level should not be changed, unless its current value is
  4174. meaningless (i.e., not one of 1,2,3,4,5).
  4175. User level determines the setting of Viper variables that are most
  4176. sensitive for VI-style look-and-feel."
  4177. (interactive)
  4178. (if (not (natnump viper-expert-level)) (setq viper-expert-level 0))
  4179. (save-window-excursion
  4180. (delete-other-windows)
  4181. ;; if 0 < viper-expert-level < viper-max-expert-level
  4182. ;; & dont-change-unless = t -- use it; else ask
  4183. (viper-ask-level dont-change-unless))
  4184. (setq viper-always t
  4185. viper-ex-style-motion t
  4186. viper-ex-style-editing t
  4187. viper-want-ctl-h-help nil)
  4188. (cond ((eq viper-expert-level 1) ; novice or beginner
  4189. (global-set-key ; in emacs-state
  4190. viper-toggle-key
  4191. (if (viper-window-display-p) 'viper-iconify 'suspend-emacs))
  4192. (setq viper-no-multiple-ESC t
  4193. viper-re-search t
  4194. viper-vi-style-in-minibuffer t
  4195. viper-search-wrap-around t
  4196. viper-electric-mode nil
  4197. viper-want-emacs-keys-in-vi nil
  4198. viper-want-emacs-keys-in-insert nil))
  4199. ((and (> viper-expert-level 1) (< viper-expert-level 5))
  4200. ;; intermediate to guru
  4201. (setq viper-no-multiple-ESC (if (viper-window-display-p)
  4202. t 'twice)
  4203. viper-electric-mode t
  4204. viper-want-emacs-keys-in-vi t
  4205. viper-want-emacs-keys-in-insert (> viper-expert-level 2))
  4206. (if (eq viper-expert-level 4) ; respect user's ex-style motion
  4207. ; and viper-no-multiple-ESC
  4208. (progn
  4209. (setq-default
  4210. viper-ex-style-editing
  4211. (viper-standard-value 'viper-ex-style-editing)
  4212. viper-ex-style-motion
  4213. (viper-standard-value 'viper-ex-style-motion))
  4214. (setq viper-ex-style-motion
  4215. (viper-standard-value 'viper-ex-style-motion)
  4216. viper-ex-style-editing
  4217. (viper-standard-value 'viper-ex-style-editing)
  4218. viper-re-search
  4219. (viper-standard-value 'viper-re-search)
  4220. viper-no-multiple-ESC
  4221. (viper-standard-value 'viper-no-multiple-ESC)))))
  4222. ;; A wizard!!
  4223. ;; Ideally, if 5 is selected, a buffer should pop up to let the
  4224. ;; user toggle the values of variables.
  4225. (t (setq-default viper-ex-style-editing
  4226. (viper-standard-value 'viper-ex-style-editing)
  4227. viper-ex-style-motion
  4228. (viper-standard-value 'viper-ex-style-motion))
  4229. (setq viper-want-ctl-h-help
  4230. (viper-standard-value 'viper-want-ctl-h-help)
  4231. viper-always
  4232. (viper-standard-value 'viper-always)
  4233. viper-no-multiple-ESC
  4234. (viper-standard-value 'viper-no-multiple-ESC)
  4235. viper-ex-style-motion
  4236. (viper-standard-value 'viper-ex-style-motion)
  4237. viper-ex-style-editing
  4238. (viper-standard-value 'viper-ex-style-editing)
  4239. viper-re-search
  4240. (viper-standard-value 'viper-re-search)
  4241. viper-electric-mode
  4242. (viper-standard-value 'viper-electric-mode)
  4243. viper-want-emacs-keys-in-vi
  4244. (viper-standard-value 'viper-want-emacs-keys-in-vi)
  4245. viper-want-emacs-keys-in-insert
  4246. (viper-standard-value 'viper-want-emacs-keys-in-insert))))
  4247. (viper-set-mode-vars-for viper-current-state)
  4248. (if (or viper-always
  4249. (and (> viper-expert-level 0) (> 5 viper-expert-level)))
  4250. (viper-set-hooks)))
  4251. ;; Ask user expert level.
  4252. (defun viper-ask-level (dont-change-unless)
  4253. (let ((ask-buffer " *viper-ask-level*")
  4254. level-changed repeated)
  4255. (save-window-excursion
  4256. (switch-to-buffer ask-buffer)
  4257. (while (or (> viper-expert-level viper-max-expert-level)
  4258. (< viper-expert-level 1)
  4259. (null dont-change-unless))
  4260. (erase-buffer)
  4261. (if repeated
  4262. (progn
  4263. (message "Invalid user level")
  4264. (beep 1))
  4265. (setq repeated t))
  4266. (setq dont-change-unless t
  4267. level-changed t)
  4268. (insert (substitute-command-keys "
  4269. Please specify your level of familiarity with the venomous VI PERil
  4270. \(and the VI Plan for Emacs Rescue).
  4271. You can change it at any time by typing `\\[viper-set-expert-level]'
  4272. 1 -- BEGINNER: Almost all Emacs features are suppressed.
  4273. Feels almost like straight Vi. File name completion and
  4274. command history in the minibuffer are thrown in as a bonus.
  4275. To use Emacs productively, you must reach level 3 or higher.
  4276. 2 -- MASTER: C-c now has its standard Emacs meaning in Vi command state,
  4277. so most Emacs commands can be used when Viper is in Vi state.
  4278. Good progress---you are well on the way to level 3!
  4279. 3 -- GRAND MASTER: Like 2, but most Emacs commands are available also
  4280. in Viper's insert state.
  4281. 4 -- GURU: Like 3, but user settings are respected for viper-no-multiple-ESC,
  4282. viper-ex-style-motion, viper-ex-style-editing, and
  4283. viper-re-search variables. Adjust these settings to your taste.
  4284. 5 -- WIZARD: Like 4, but user settings are also respected for viper-always,
  4285. viper-electric-mode, viper-want-ctl-h-help, viper-want-emacs-keys-in-vi,
  4286. and viper-want-emacs-keys-in-insert. Adjust these to your taste.
  4287. Please, specify your level now: "))
  4288. (setq viper-expert-level (- (viper-read-char-exclusive) ?0))
  4289. ) ; end while
  4290. ;; tell the user if level was changed
  4291. (and level-changed
  4292. (progn
  4293. (insert
  4294. (format "\n\n\n\n\n\t\tYou have selected user level %d"
  4295. viper-expert-level))
  4296. (if (y-or-n-p "Do you wish to make this change permanent? ")
  4297. ;; save the setting for viper-expert-level
  4298. (viper-save-setting
  4299. 'viper-expert-level
  4300. (format "Saving user level %d ..." viper-expert-level)
  4301. viper-custom-file-name))
  4302. ))
  4303. (bury-buffer) ; remove ask-buffer from screen
  4304. (message "")
  4305. )))
  4306. (defun viper-nil ()
  4307. (interactive)
  4308. (beep 1))
  4309. ;; FIXME Use register-read-with-preview?
  4310. ;; if ENFORCE-BUFFER is not nil, error if CHAR is a marker in another buffer
  4311. (defun viper-register-to-point (char &optional enforce-buffer)
  4312. "Like `jump-to-register', but switches to another buffer in another window."
  4313. (interactive "cViper register to point: ")
  4314. (let ((val (get-register char)))
  4315. (cond
  4316. ((and (fboundp 'frame-configuration-p)
  4317. (frame-configuration-p val))
  4318. (set-frame-configuration val))
  4319. ((window-configuration-p val)
  4320. (set-window-configuration val))
  4321. ((viper-valid-marker val)
  4322. (if (and enforce-buffer
  4323. (not (equal (current-buffer) (marker-buffer val))))
  4324. (error (concat viper-EmptyTextmarker " in this buffer")
  4325. (viper-int-to-char (1- (+ char ?a)))))
  4326. (pop-to-buffer (marker-buffer val))
  4327. (goto-char val))
  4328. ((and (consp val) (eq (car val) 'file))
  4329. (find-file (cdr val)))
  4330. (t
  4331. (error viper-EmptyTextmarker (viper-int-to-char (1- (+ char ?a))))))))
  4332. (defun viper-save-kill-buffer ()
  4333. "Save then kill current buffer."
  4334. (interactive)
  4335. (if (< viper-expert-level 2)
  4336. (save-buffers-kill-emacs)
  4337. (if (buffer-modified-p) (save-buffer))
  4338. (kill-buffer (current-buffer))))
  4339. ;;; Bug Report
  4340. (defun viper-submit-report ()
  4341. "Submit bug report on Viper."
  4342. (interactive)
  4343. (let ((reporter-prompt-for-summary-p t)
  4344. (viper-device-type (viper-device-type))
  4345. color-display-p frame-parameters
  4346. minibuffer-emacs-face minibuffer-vi-face minibuffer-insert-face
  4347. varlist salutation window-config)
  4348. ;; If mode info is needed, add variable to `let' and then set it below,
  4349. ;; like we did with color-display-p.
  4350. (setq color-display-p (if (viper-window-display-p)
  4351. (viper-color-display-p)
  4352. 'non-x)
  4353. minibuffer-vi-face (if (viper-has-face-support-p)
  4354. (viper-get-face viper-minibuffer-vi-face)
  4355. 'non-x)
  4356. minibuffer-insert-face (if (viper-has-face-support-p)
  4357. (viper-get-face
  4358. viper-minibuffer-insert-face)
  4359. 'non-x)
  4360. minibuffer-emacs-face (if (viper-has-face-support-p)
  4361. (viper-get-face
  4362. viper-minibuffer-emacs-face)
  4363. 'non-x)
  4364. frame-parameters (if (fboundp 'frame-parameters)
  4365. (frame-parameters (selected-frame))))
  4366. (setq varlist (list 'viper-vi-minibuffer-minor-mode
  4367. 'viper-insert-minibuffer-minor-mode
  4368. 'viper-vi-intercept-minor-mode
  4369. 'viper-vi-local-user-minor-mode
  4370. 'viper-vi-kbd-minor-mode
  4371. 'viper-vi-global-user-minor-mode
  4372. 'viper-vi-state-modifier-minor-mode
  4373. 'viper-vi-diehard-minor-mode
  4374. 'viper-vi-basic-minor-mode
  4375. 'viper-replace-minor-mode
  4376. 'viper-insert-intercept-minor-mode
  4377. 'viper-insert-local-user-minor-mode
  4378. 'viper-insert-kbd-minor-mode
  4379. 'viper-insert-global-user-minor-mode
  4380. 'viper-insert-state-modifier-minor-mode
  4381. 'viper-insert-diehard-minor-mode
  4382. 'viper-insert-basic-minor-mode
  4383. 'viper-emacs-intercept-minor-mode
  4384. 'viper-emacs-local-user-minor-mode
  4385. 'viper-emacs-kbd-minor-mode
  4386. 'viper-emacs-global-user-minor-mode
  4387. 'viper-emacs-state-modifier-minor-mode
  4388. 'viper-automatic-iso-accents
  4389. 'viper-special-input-method
  4390. 'viper-want-emacs-keys-in-insert
  4391. 'viper-want-emacs-keys-in-vi
  4392. 'viper-keep-point-on-undo
  4393. 'viper-no-multiple-ESC
  4394. 'viper-electric-mode
  4395. 'viper-ESC-key
  4396. 'viper-want-ctl-h-help
  4397. 'viper-ex-style-editing
  4398. 'viper-delete-backwards-in-replace
  4399. 'viper-vi-style-in-minibuffer
  4400. 'viper-vi-state-hook
  4401. 'viper-insert-state-hook
  4402. 'viper-replace-state-hook
  4403. 'viper-emacs-state-hook
  4404. 'ex-cycle-other-window
  4405. 'ex-cycle-through-non-files
  4406. 'viper-expert-level
  4407. 'major-mode
  4408. 'viper-device-type
  4409. 'color-display-p
  4410. 'frame-parameters
  4411. 'minibuffer-vi-face
  4412. 'minibuffer-insert-face
  4413. 'minibuffer-emacs-face
  4414. ))
  4415. (setq salutation "
  4416. Congratulations! You may have unearthed a bug in Viper!
  4417. Please mail a concise, accurate summary of the problem to the address above.
  4418. -------------------------------------------------------------------")
  4419. (setq window-config (current-window-configuration))
  4420. (with-output-to-temp-buffer " *viper-info*"
  4421. (switch-to-buffer " *viper-info*")
  4422. (delete-other-windows)
  4423. (princ "
  4424. PLEASE FOLLOW THESE PROCEDURES
  4425. ------------------------------
  4426. Before reporting a bug, please verify that it is related to Viper, and is
  4427. not caused by other packages you are using.
  4428. Don't report compilation warnings, unless you are certain that there is a
  4429. problem. These warnings are normal and unavoidable.
  4430. Please note that users should not modify variables and keymaps other than
  4431. those advertised in the manual. Such `customization' is likely to crash
  4432. Viper, as it would any other improperly customized Emacs package.
  4433. If you are reporting an error message received while executing one of the
  4434. Viper commands, type:
  4435. M-x set-variable <Return> debug-on-error <Return> t <Return>
  4436. Then reproduce the error. The above command will cause Emacs to produce a
  4437. back trace of the execution that leads to the error. Please include this
  4438. trace in your bug report.
  4439. If you believe that one of Viper's commands goes into an infinite loop
  4440. \(e.g., Emacs freezes), type:
  4441. M-x set-variable <Return> debug-on-quit <Return> t <Return>
  4442. Then reproduce the problem. Wait for a few seconds, then type C-g to abort
  4443. the current command. Include the resulting back trace in the bug report.
  4444. Mail anyway (y or n)? ")
  4445. (if (y-or-n-p "Mail anyway? ")
  4446. ()
  4447. (set-window-configuration window-config)
  4448. (error "Bug report aborted")))
  4449. (require 'reporter)
  4450. (set-window-configuration window-config)
  4451. (reporter-submit-bug-report
  4452. "kifer@cs.stonybrook.edu, bug-gnu-emacs@gnu.org"
  4453. (viper-version)
  4454. varlist
  4455. nil 'delete-other-windows
  4456. salutation)))
  4457. ;;; viper-cmd.el ends here