taglist.vim 144 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546
  1. " File: taglist.vim
  2. " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
  3. " Version: 4.5
  4. " Last Modified: September 21, 2007
  5. " Copyright: Copyright (C) 2002-2007 Yegappan Lakshmanan
  6. " Permission is hereby granted to use and distribute this code,
  7. " with or without modifications, provided that this copyright
  8. " notice is copied with it. Like anything else that's free,
  9. " taglist.vim is provided *as is* and comes with no warranty of any
  10. " kind, either expressed or implied. In no event will the copyright
  11. " holder be liable for any damamges resulting from the use of this
  12. " software.
  13. "
  14. " The "Tag List" plugin is a source code browser plugin for Vim and provides
  15. " an overview of the structure of the programming language files and allows
  16. " you to efficiently browse through source code files for different
  17. " programming languages. You can visit the taglist plugin home page for more
  18. " information:
  19. "
  20. " http://vim-taglist.sourceforge.net
  21. "
  22. " You can subscribe to the taglist mailing list to post your questions
  23. " or suggestions for improvement or to report bugs. Visit the following
  24. " page for subscribing to the mailing list:
  25. "
  26. " http://groups.yahoo.com/group/taglist/
  27. "
  28. " For more information about using this plugin, after installing the
  29. " taglist plugin, use the ":help taglist" command.
  30. "
  31. " Installation
  32. " ------------
  33. " 1. Download the taglist.zip file and unzip the files to the $HOME/.vim
  34. " or the $HOME/vimfiles or the $VIM/vimfiles directory. This should
  35. " unzip the following two files (the directory structure should be
  36. " preserved):
  37. "
  38. " plugin/taglist.vim - main taglist plugin file
  39. " doc/taglist.txt - documentation (help) file
  40. "
  41. " Refer to the 'add-plugin', 'add-global-plugin' and 'runtimepath'
  42. " Vim help pages for more details about installing Vim plugins.
  43. " 2. Change to the $HOME/.vim/doc or $HOME/vimfiles/doc or
  44. " $VIM/vimfiles/doc directory, start Vim and run the ":helptags ."
  45. " command to process the taglist help file.
  46. " 3. If the exuberant ctags utility is not present in your PATH, then set the
  47. " Tlist_Ctags_Cmd variable to point to the location of the exuberant ctags
  48. " utility (not to the directory) in the .vimrc file.
  49. " 4. If you are running a terminal/console version of Vim and the
  50. " terminal doesn't support changing the window width then set the
  51. " 'Tlist_Inc_Winwidth' variable to 0 in the .vimrc file.
  52. " 5. Restart Vim.
  53. " 6. You can now use the ":TlistToggle" command to open/close the taglist
  54. " window. You can use the ":help taglist" command to get more
  55. " information about using the taglist plugin.
  56. "
  57. " ****************** Do not modify after this line ************************
  58. " Line continuation used here
  59. let s:cpo_save = &cpo
  60. set cpo&vim
  61. if !exists('loaded_taglist')
  62. " First time loading the taglist plugin
  63. "
  64. " To speed up the loading of Vim, the taglist plugin uses autoload
  65. " mechanism to load the taglist functions.
  66. " Only define the configuration variables, user commands and some
  67. " auto-commands and finish sourcing the file
  68. " The taglist plugin requires the built-in Vim system() function. If this
  69. " function is not available, then don't load the plugin.
  70. if !exists('*system')
  71. echomsg 'Taglist: Vim system() built-in function is not available. ' .
  72. \ 'Plugin is not loaded.'
  73. let loaded_taglist = 'no'
  74. let &cpo = s:cpo_save
  75. finish
  76. endif
  77. " Location of the exuberant ctags tool
  78. if !exists('Tlist_Ctags_Cmd')
  79. if executable('exuberant-ctags')
  80. " On Debian Linux, exuberant ctags is installed
  81. " as exuberant-ctags
  82. let Tlist_Ctags_Cmd = 'exuberant-ctags'
  83. elseif executable('exctags')
  84. " On Free-BSD, exuberant ctags is installed as exctags
  85. let Tlist_Ctags_Cmd = 'exctags'
  86. elseif executable('ctags')
  87. let Tlist_Ctags_Cmd = 'ctags'
  88. elseif executable('ctags.exe')
  89. let Tlist_Ctags_Cmd = 'ctags.exe'
  90. elseif executable('tags')
  91. let Tlist_Ctags_Cmd = 'tags'
  92. else
  93. echomsg 'Taglist: Exuberant ctags (http://ctags.sf.net) ' .
  94. \ 'not found in PATH. Plugin is not loaded.'
  95. " Skip loading the plugin
  96. let loaded_taglist = 'no'
  97. let &cpo = s:cpo_save
  98. finish
  99. endif
  100. endif
  101. " Automatically open the taglist window on Vim startup
  102. if !exists('Tlist_Auto_Open')
  103. let Tlist_Auto_Open = 0
  104. endif
  105. " When the taglist window is toggle opened, move the cursor to the
  106. " taglist window
  107. if !exists('Tlist_GainFocus_On_ToggleOpen')
  108. let Tlist_GainFocus_On_ToggleOpen = 0
  109. endif
  110. " Process files even when the taglist window is not open
  111. if !exists('Tlist_Process_File_Always')
  112. let Tlist_Process_File_Always = 0
  113. endif
  114. if !exists('Tlist_Show_Menu')
  115. let Tlist_Show_Menu = 0
  116. endif
  117. " Tag listing sort type - 'name' or 'order'
  118. if !exists('Tlist_Sort_Type')
  119. let Tlist_Sort_Type = 'order'
  120. endif
  121. " Tag listing window split (horizontal/vertical) control
  122. if !exists('Tlist_Use_Horiz_Window')
  123. let Tlist_Use_Horiz_Window = 0
  124. endif
  125. " Open the vertically split taglist window on the left or on the right
  126. " side. This setting is relevant only if Tlist_Use_Horiz_Window is set to
  127. " zero (i.e. only for vertically split windows)
  128. if !exists('Tlist_Use_Right_Window')
  129. let Tlist_Use_Right_Window = 0
  130. endif
  131. " Increase Vim window width to display vertically split taglist window.
  132. " For MS-Windows version of Vim running in a MS-DOS window, this must be
  133. " set to 0 otherwise the system may hang due to a Vim limitation.
  134. if !exists('Tlist_Inc_Winwidth')
  135. if (has('win16') || has('win95')) && !has('gui_running')
  136. let Tlist_Inc_Winwidth = 0
  137. else
  138. let Tlist_Inc_Winwidth = 1
  139. endif
  140. endif
  141. " Vertically split taglist window width setting
  142. if !exists('Tlist_WinWidth')
  143. let Tlist_WinWidth = 30
  144. endif
  145. " Horizontally split taglist window height setting
  146. if !exists('Tlist_WinHeight')
  147. let Tlist_WinHeight = 10
  148. endif
  149. " Display tag prototypes or tag names in the taglist window
  150. if !exists('Tlist_Display_Prototype')
  151. let Tlist_Display_Prototype = 0
  152. endif
  153. " Display tag scopes in the taglist window
  154. if !exists('Tlist_Display_Tag_Scope')
  155. let Tlist_Display_Tag_Scope = 1
  156. endif
  157. " Use single left mouse click to jump to a tag. By default this is disabled.
  158. " Only double click using the mouse will be processed.
  159. if !exists('Tlist_Use_SingleClick')
  160. let Tlist_Use_SingleClick = 0
  161. endif
  162. " Control whether additional help is displayed as part of the taglist or
  163. " not. Also, controls whether empty lines are used to separate the tag
  164. " tree.
  165. if !exists('Tlist_Compact_Format')
  166. let Tlist_Compact_Format = 0
  167. endif
  168. " Exit Vim if only the taglist window is currently open. By default, this is
  169. " set to zero.
  170. if !exists('Tlist_Exit_OnlyWindow')
  171. let Tlist_Exit_OnlyWindow = 0
  172. endif
  173. " Automatically close the folds for the non-active files in the taglist
  174. " window
  175. if !exists('Tlist_File_Fold_Auto_Close')
  176. let Tlist_File_Fold_Auto_Close = 0
  177. endif
  178. " Close the taglist window when a tag is selected
  179. if !exists('Tlist_Close_On_Select')
  180. let Tlist_Close_On_Select = 0
  181. endif
  182. " Automatically update the taglist window to display tags for newly
  183. " edited files
  184. if !exists('Tlist_Auto_Update')
  185. let Tlist_Auto_Update = 1
  186. endif
  187. " Automatically highlight the current tag
  188. if !exists('Tlist_Auto_Highlight_Tag')
  189. let Tlist_Auto_Highlight_Tag = 1
  190. endif
  191. " Automatically highlight the current tag on entering a buffer
  192. if !exists('Tlist_Highlight_Tag_On_BufEnter')
  193. let Tlist_Highlight_Tag_On_BufEnter = 1
  194. endif
  195. " Enable fold column to display the folding for the tag tree
  196. if !exists('Tlist_Enable_Fold_Column')
  197. let Tlist_Enable_Fold_Column = 1
  198. endif
  199. " Display the tags for only one file in the taglist window
  200. if !exists('Tlist_Show_One_File')
  201. let Tlist_Show_One_File = 0
  202. endif
  203. if !exists('Tlist_Max_Submenu_Items')
  204. let Tlist_Max_Submenu_Items = 20
  205. endif
  206. if !exists('Tlist_Max_Tag_Length')
  207. let Tlist_Max_Tag_Length = 10
  208. endif
  209. " Do not change the name of the taglist title variable. The winmanager
  210. " plugin relies on this name to determine the title for the taglist
  211. " plugin.
  212. let TagList_title = "__Tag_List__"
  213. " Taglist debug messages
  214. let s:tlist_msg = ''
  215. " Define the taglist autocommand to automatically open the taglist window
  216. " on Vim startup
  217. if g:Tlist_Auto_Open
  218. autocmd VimEnter * nested call s:Tlist_Window_Check_Auto_Open()
  219. endif
  220. " Refresh the taglist
  221. if g:Tlist_Process_File_Always
  222. autocmd BufEnter * call s:Tlist_Refresh()
  223. endif
  224. if g:Tlist_Show_Menu
  225. autocmd GUIEnter * call s:Tlist_Menu_Init()
  226. endif
  227. " When the taglist buffer is created when loading a Vim session file,
  228. " the taglist buffer needs to be initialized. The BufFilePost event
  229. " is used to handle this case.
  230. autocmd BufFilePost __Tag_List__ call s:Tlist_Vim_Session_Load()
  231. " Define the user commands to manage the taglist window
  232. command! -nargs=0 -bar TlistToggle call s:Tlist_Window_Toggle()
  233. command! -nargs=0 -bar TlistOpen call s:Tlist_Window_Open()
  234. " For backwards compatiblity define the Tlist command
  235. command! -nargs=0 -bar Tlist TlistToggle
  236. command! -nargs=+ -complete=file TlistAddFiles
  237. \ call s:Tlist_Add_Files(<f-args>)
  238. command! -nargs=+ -complete=dir TlistAddFilesRecursive
  239. \ call s:Tlist_Add_Files_Recursive(<f-args>)
  240. command! -nargs=0 -bar TlistClose call s:Tlist_Window_Close()
  241. command! -nargs=0 -bar TlistUpdate call s:Tlist_Update_Current_File()
  242. command! -nargs=0 -bar TlistHighlightTag call s:Tlist_Window_Highlight_Tag(
  243. \ fnamemodify(bufname('%'), ':p'), line('.'), 2, 1)
  244. " For backwards compatiblity define the TlistSync command
  245. command! -nargs=0 -bar TlistSync TlistHighlightTag
  246. command! -nargs=* -complete=buffer TlistShowPrototype
  247. \ echo Tlist_Get_Tag_Prototype_By_Line(<f-args>)
  248. command! -nargs=* -complete=buffer TlistShowTag
  249. \ echo Tlist_Get_Tagname_By_Line(<f-args>)
  250. command! -nargs=* -complete=file TlistSessionLoad
  251. \ call s:Tlist_Session_Load(<q-args>)
  252. command! -nargs=* -complete=file TlistSessionSave
  253. \ call s:Tlist_Session_Save(<q-args>)
  254. command! -bar TlistLock let Tlist_Auto_Update=0
  255. command! -bar TlistUnlock let Tlist_Auto_Update=1
  256. " Commands for enabling/disabling debug and to display debug messages
  257. command! -nargs=? -complete=file -bar TlistDebug
  258. \ call s:Tlist_Debug_Enable(<q-args>)
  259. command! -nargs=0 -bar TlistUndebug call s:Tlist_Debug_Disable()
  260. command! -nargs=0 -bar TlistMessages call s:Tlist_Debug_Show()
  261. " Define autocommands to autoload the taglist plugin when needed.
  262. " Trick to get the current script ID
  263. map <SID>xx <SID>xx
  264. let s:tlist_sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$',
  265. \ '\1', '')
  266. unmap <SID>xx
  267. exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_* source ' .
  268. \ escape(expand('<sfile>'), ' ')
  269. exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Window_* source ' .
  270. \ escape(expand('<sfile>'), ' ')
  271. exe 'autocmd FuncUndefined *' . s:tlist_sid . 'Tlist_Menu_* source ' .
  272. \ escape(expand('<sfile>'), ' ')
  273. exe 'autocmd FuncUndefined Tlist_* source ' .
  274. \ escape(expand('<sfile>'), ' ')
  275. exe 'autocmd FuncUndefined TagList_* source ' .
  276. \ escape(expand('<sfile>'), ' ')
  277. let loaded_taglist = 'fast_load_done'
  278. if g:Tlist_Show_Menu && has('gui_running')
  279. call s:Tlist_Menu_Init()
  280. endif
  281. " restore 'cpo'
  282. let &cpo = s:cpo_save
  283. finish
  284. endif
  285. if !exists('s:tlist_sid')
  286. " Two or more versions of taglist plugin are installed. Don't
  287. " load this version of the plugin.
  288. finish
  289. endif
  290. unlet! s:tlist_sid
  291. if loaded_taglist != 'fast_load_done'
  292. " restore 'cpo'
  293. let &cpo = s:cpo_save
  294. finish
  295. endif
  296. " Taglist plugin functionality is available
  297. let loaded_taglist = 'available'
  298. "------------------- end of user configurable options --------------------
  299. " Default language specific settings for supported file types and tag types
  300. "
  301. " Variable name format:
  302. "
  303. " s:tlist_def_{vim_ftype}_settings
  304. "
  305. " vim_ftype - Filetype detected by Vim
  306. "
  307. " Value format:
  308. "
  309. " <ctags_ftype>;<flag>:<name>;<flag>:<name>;...
  310. "
  311. " ctags_ftype - File type supported by exuberant ctags
  312. " flag - Flag supported by exuberant ctags to generate a tag type
  313. " name - Name of the tag type used in the taglist window to display the
  314. " tags of this type
  315. "
  316. " assembly language
  317. let s:tlist_def_asm_settings = 'asm;d:define;l:label;m:macro;t:type'
  318. " aspperl language
  319. let s:tlist_def_aspperl_settings = 'asp;f:function;s:sub;v:variable'
  320. " aspvbs language
  321. let s:tlist_def_aspvbs_settings = 'asp;f:function;s:sub;v:variable'
  322. " awk language
  323. let s:tlist_def_awk_settings = 'awk;f:function'
  324. " beta language
  325. let s:tlist_def_beta_settings = 'beta;f:fragment;s:slot;v:pattern'
  326. " c language
  327. let s:tlist_def_c_settings = 'c;d:macro;g:enum;s:struct;u:union;t:typedef;' .
  328. \ 'v:variable;f:function'
  329. " c++ language
  330. let s:tlist_def_cpp_settings = 'c++;n:namespace;v:variable;d:macro;t:typedef;' .
  331. \ 'c:class;g:enum;s:struct;u:union;f:function'
  332. " c# language
  333. let s:tlist_def_cs_settings = 'c#;d:macro;t:typedef;n:namespace;c:class;' .
  334. \ 'E:event;g:enum;s:struct;i:interface;' .
  335. \ 'p:properties;m:method'
  336. " cobol language
  337. let s:tlist_def_cobol_settings = 'cobol;d:data;f:file;g:group;p:paragraph;' .
  338. \ 'P:program;s:section'
  339. " eiffel language
  340. let s:tlist_def_eiffel_settings = 'eiffel;c:class;f:feature'
  341. " erlang language
  342. let s:tlist_def_erlang_settings = 'erlang;d:macro;r:record;m:module;f:function'
  343. " expect (same as tcl) language
  344. let s:tlist_def_expect_settings = 'tcl;c:class;f:method;p:procedure'
  345. " fortran language
  346. let s:tlist_def_fortran_settings = 'fortran;p:program;b:block data;' .
  347. \ 'c:common;e:entry;i:interface;k:type;l:label;m:module;' .
  348. \ 'n:namelist;t:derived;v:variable;f:function;s:subroutine'
  349. " HTML language
  350. let s:tlist_def_html_settings = 'html;a:anchor;f:javascript function'
  351. " java language
  352. let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' .
  353. \ 'f:field;m:method'
  354. " javascript language
  355. let s:tlist_def_javascript_settings = 'javascript;f:function'
  356. " lisp language
  357. let s:tlist_def_lisp_settings = 'lisp;f:function'
  358. " lua language
  359. let s:tlist_def_lua_settings = 'lua;f:function'
  360. " makefiles
  361. let s:tlist_def_make_settings = 'make;m:macro'
  362. " pascal language
  363. let s:tlist_def_pascal_settings = 'pascal;f:function;p:procedure'
  364. " perl language
  365. let s:tlist_def_perl_settings = 'perl;c:constant;l:label;p:package;s:subroutine'
  366. " php language
  367. let s:tlist_def_php_settings = 'php;c:class;d:constant;v:variable;f:function'
  368. " python language
  369. let s:tlist_def_python_settings = 'python;c:class;m:member;f:function'
  370. " rexx language
  371. let s:tlist_def_rexx_settings = 'rexx;s:subroutine'
  372. " ruby language
  373. let s:tlist_def_ruby_settings = 'ruby;c:class;f:method;F:function;' .
  374. \ 'm:singleton method'
  375. " scheme language
  376. let s:tlist_def_scheme_settings = 'scheme;s:set;f:function'
  377. " shell language
  378. let s:tlist_def_sh_settings = 'sh;f:function'
  379. " C shell language
  380. let s:tlist_def_csh_settings = 'sh;f:function'
  381. " Z shell language
  382. let s:tlist_def_zsh_settings = 'sh;f:function'
  383. " slang language
  384. let s:tlist_def_slang_settings = 'slang;n:namespace;f:function'
  385. " sml language
  386. let s:tlist_def_sml_settings = 'sml;e:exception;c:functor;s:signature;' .
  387. \ 'r:structure;t:type;v:value;f:function'
  388. " sql language
  389. let s:tlist_def_sql_settings = 'sql;c:cursor;F:field;P:package;r:record;' .
  390. \ 's:subtype;t:table;T:trigger;v:variable;f:function;p:procedure'
  391. " tcl language
  392. let s:tlist_def_tcl_settings = 'tcl;c:class;f:method;m:method;p:procedure'
  393. " vera language
  394. let s:tlist_def_vera_settings = 'vera;c:class;d:macro;e:enumerator;' .
  395. \ 'f:function;g:enum;m:member;p:program;' .
  396. \ 'P:prototype;t:task;T:typedef;v:variable;' .
  397. \ 'x:externvar'
  398. "verilog language
  399. let s:tlist_def_verilog_settings = 'verilog;m:module;c:constant;P:parameter;' .
  400. \ 'e:event;r:register;t:task;w:write;p:port;v:variable;f:function'
  401. " vim language
  402. let s:tlist_def_vim_settings = 'vim;a:autocmds;v:variable;f:function'
  403. " yacc language
  404. let s:tlist_def_yacc_settings = 'yacc;l:label'
  405. "------------------- end of language specific options --------------------
  406. " Vim window size is changed by the taglist plugin or not
  407. let s:tlist_winsize_chgd = -1
  408. " Taglist window is maximized or not
  409. let s:tlist_win_maximized = 0
  410. " Name of files in the taglist
  411. let s:tlist_file_names=''
  412. " Number of files in the taglist
  413. let s:tlist_file_count = 0
  414. " Number of filetypes supported by taglist
  415. let s:tlist_ftype_count = 0
  416. " Is taglist part of other plugins like winmanager or cream?
  417. let s:tlist_app_name = "none"
  418. " Are we displaying brief help text
  419. let s:tlist_brief_help = 1
  420. " List of files removed on user request
  421. let s:tlist_removed_flist = ""
  422. " Index of current file displayed in the taglist window
  423. let s:tlist_cur_file_idx = -1
  424. " Taglist menu is empty or not
  425. let s:tlist_menu_empty = 1
  426. " An autocommand is used to refresh the taglist window when entering any
  427. " buffer. We don't want to refresh the taglist window if we are entering the
  428. " file window from one of the taglist functions. The 'Tlist_Skip_Refresh'
  429. " variable is used to skip the refresh of the taglist window and is set
  430. " and cleared appropriately.
  431. let s:Tlist_Skip_Refresh = 0
  432. " Tlist_Window_Display_Help()
  433. function! s:Tlist_Window_Display_Help()
  434. if s:tlist_app_name == "winmanager"
  435. " To handle a bug in the winmanager plugin, add a space at the
  436. " last line
  437. call setline('$', ' ')
  438. endif
  439. if s:tlist_brief_help
  440. " Add the brief help
  441. call append(0, '" Press <F1> to display help text')
  442. else
  443. " Add the extensive help
  444. call append(0, '" <enter> : Jump to tag definition')
  445. call append(1, '" o : Jump to tag definition in new window')
  446. call append(2, '" p : Preview the tag definition')
  447. call append(3, '" <space> : Display tag prototype')
  448. call append(4, '" u : Update tag list')
  449. call append(5, '" s : Select sort field')
  450. call append(6, '" d : Remove file from taglist')
  451. call append(7, '" x : Zoom-out/Zoom-in taglist window')
  452. call append(8, '" + : Open a fold')
  453. call append(9, '" - : Close a fold')
  454. call append(10, '" * : Open all folds')
  455. call append(11, '" = : Close all folds')
  456. call append(12, '" [[ : Move to the start of previous file')
  457. call append(13, '" ]] : Move to the start of next file')
  458. call append(14, '" q : Close the taglist window')
  459. call append(15, '" <F1> : Remove help text')
  460. endif
  461. endfunction
  462. " Tlist_Window_Toggle_Help_Text()
  463. " Toggle taglist plugin help text between the full version and the brief
  464. " version
  465. function! s:Tlist_Window_Toggle_Help_Text()
  466. if g:Tlist_Compact_Format
  467. " In compact display mode, do not display help
  468. return
  469. endif
  470. " Include the empty line displayed after the help text
  471. let brief_help_size = 1
  472. let full_help_size = 16
  473. setlocal modifiable
  474. " Set report option to a huge value to prevent informational messages
  475. " while deleting the lines
  476. let old_report = &report
  477. set report=99999
  478. " Remove the currently highlighted tag. Otherwise, the help text
  479. " might be highlighted by mistake
  480. match none
  481. " Toggle between brief and full help text
  482. if s:tlist_brief_help
  483. let s:tlist_brief_help = 0
  484. " Remove the previous help
  485. exe '1,' . brief_help_size . ' delete _'
  486. " Adjust the start/end line numbers for the files
  487. call s:Tlist_Window_Update_Line_Offsets(0, 1, full_help_size - brief_help_size)
  488. else
  489. let s:tlist_brief_help = 1
  490. " Remove the previous help
  491. exe '1,' . full_help_size . ' delete _'
  492. " Adjust the start/end line numbers for the files
  493. call s:Tlist_Window_Update_Line_Offsets(0, 0, full_help_size - brief_help_size)
  494. endif
  495. call s:Tlist_Window_Display_Help()
  496. " Restore the report option
  497. let &report = old_report
  498. setlocal nomodifiable
  499. endfunction
  500. " Taglist debug support
  501. let s:tlist_debug = 0
  502. " File for storing the debug messages
  503. let s:tlist_debug_file = ''
  504. " Tlist_Debug_Enable
  505. " Enable logging of taglist debug messages.
  506. function! s:Tlist_Debug_Enable(...)
  507. let s:tlist_debug = 1
  508. " Check whether a valid file name is supplied.
  509. if a:1 != ''
  510. let s:tlist_debug_file = fnamemodify(a:1, ':p')
  511. " Empty the log file
  512. exe 'redir! > ' . s:tlist_debug_file
  513. redir END
  514. " Check whether the log file is present/created
  515. if !filewritable(s:tlist_debug_file)
  516. call s:Tlist_Warning_Msg('Taglist: Unable to create log file '
  517. \ . s:tlist_debug_file)
  518. let s:tlist_debug_file = ''
  519. endif
  520. endif
  521. endfunction
  522. " Tlist_Debug_Disable
  523. " Disable logging of taglist debug messages.
  524. function! s:Tlist_Debug_Disable(...)
  525. let s:tlist_debug = 0
  526. let s:tlist_debug_file = ''
  527. endfunction
  528. " Tlist_Debug_Show
  529. " Display the taglist debug messages in a new window
  530. function! s:Tlist_Debug_Show()
  531. if s:tlist_msg == ''
  532. call s:Tlist_Warning_Msg('Taglist: No debug messages')
  533. return
  534. endif
  535. " Open a new window to display the taglist debug messages
  536. new taglist_debug.txt
  537. " Delete all the lines (if the buffer already exists)
  538. silent! %delete _
  539. " Add the messages
  540. silent! put =s:tlist_msg
  541. " Move the cursor to the first line
  542. normal! gg
  543. endfunction
  544. " Tlist_Log_Msg
  545. " Log the supplied debug message along with the time
  546. function! s:Tlist_Log_Msg(msg)
  547. if s:tlist_debug
  548. if s:tlist_debug_file != ''
  549. exe 'redir >> ' . s:tlist_debug_file
  550. silent echon strftime('%H:%M:%S') . ': ' . a:msg . "\n"
  551. redir END
  552. else
  553. " Log the message into a variable
  554. " Retain only the last 3000 characters
  555. let len = strlen(s:tlist_msg)
  556. if len > 3000
  557. let s:tlist_msg = strpart(s:tlist_msg, len - 3000)
  558. endif
  559. let s:tlist_msg = s:tlist_msg . strftime('%H:%M:%S') . ': ' .
  560. \ a:msg . "\n"
  561. endif
  562. endif
  563. endfunction
  564. " Tlist_Warning_Msg()
  565. " Display a message using WarningMsg highlight group
  566. function! s:Tlist_Warning_Msg(msg)
  567. echohl WarningMsg
  568. echomsg a:msg
  569. echohl None
  570. endfunction
  571. " Last returned file index for file name lookup.
  572. " Used to speed up file lookup
  573. let s:tlist_file_name_idx_cache = -1
  574. " Tlist_Get_File_Index()
  575. " Return the index of the specified filename
  576. function! s:Tlist_Get_File_Index(fname)
  577. if s:tlist_file_count == 0 || a:fname == ''
  578. return -1
  579. endif
  580. " If the new filename is same as the last accessed filename, then
  581. " return that index
  582. if s:tlist_file_name_idx_cache != -1 &&
  583. \ s:tlist_file_name_idx_cache < s:tlist_file_count
  584. if s:tlist_{s:tlist_file_name_idx_cache}_filename == a:fname
  585. " Same as the last accessed file
  586. return s:tlist_file_name_idx_cache
  587. endif
  588. endif
  589. " First, check whether the filename is present
  590. let s_fname = a:fname . "\n"
  591. let i = stridx(s:tlist_file_names, s_fname)
  592. if i == -1
  593. let s:tlist_file_name_idx_cache = -1
  594. return -1
  595. endif
  596. " Second, compute the file name index
  597. let nl_txt = substitute(strpart(s:tlist_file_names, 0, i), "[^\n]", '', 'g')
  598. let s:tlist_file_name_idx_cache = strlen(nl_txt)
  599. return s:tlist_file_name_idx_cache
  600. endfunction
  601. " Last returned file index for line number lookup.
  602. " Used to speed up file lookup
  603. let s:tlist_file_lnum_idx_cache = -1
  604. " Tlist_Window_Get_File_Index_By_Linenum()
  605. " Return the index of the filename present in the specified line number
  606. " Line number refers to the line number in the taglist window
  607. function! s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
  608. call s:Tlist_Log_Msg('Tlist_Window_Get_File_Index_By_Linenum (' . a:lnum . ')')
  609. " First try to see whether the new line number is within the range
  610. " of the last returned file
  611. if s:tlist_file_lnum_idx_cache != -1 &&
  612. \ s:tlist_file_lnum_idx_cache < s:tlist_file_count
  613. if a:lnum >= s:tlist_{s:tlist_file_lnum_idx_cache}_start &&
  614. \ a:lnum <= s:tlist_{s:tlist_file_lnum_idx_cache}_end
  615. return s:tlist_file_lnum_idx_cache
  616. endif
  617. endif
  618. let fidx = -1
  619. if g:Tlist_Show_One_File
  620. " Displaying only one file in the taglist window. Check whether
  621. " the line is within the tags displayed for that file
  622. if s:tlist_cur_file_idx != -1
  623. if a:lnum >= s:tlist_{s:tlist_cur_file_idx}_start
  624. \ && a:lnum <= s:tlist_{s:tlist_cur_file_idx}_end
  625. let fidx = s:tlist_cur_file_idx
  626. endif
  627. endif
  628. else
  629. " Do a binary search in the taglist
  630. let left = 0
  631. let right = s:tlist_file_count - 1
  632. while left < right
  633. let mid = (left + right) / 2
  634. if a:lnum >= s:tlist_{mid}_start && a:lnum <= s:tlist_{mid}_end
  635. let s:tlist_file_lnum_idx_cache = mid
  636. return mid
  637. endif
  638. if a:lnum < s:tlist_{mid}_start
  639. let right = mid - 1
  640. else
  641. let left = mid + 1
  642. endif
  643. endwhile
  644. if left >= 0 && left < s:tlist_file_count
  645. \ && a:lnum >= s:tlist_{left}_start
  646. \ && a:lnum <= s:tlist_{left}_end
  647. let fidx = left
  648. endif
  649. endif
  650. let s:tlist_file_lnum_idx_cache = fidx
  651. return fidx
  652. endfunction
  653. " Tlist_Exe_Cmd_No_Acmds
  654. " Execute the specified Ex command after disabling autocommands
  655. function! s:Tlist_Exe_Cmd_No_Acmds(cmd)
  656. let old_eventignore = &eventignore
  657. set eventignore=all
  658. exe a:cmd
  659. let &eventignore = old_eventignore
  660. endfunction
  661. " Tlist_Skip_File()
  662. " Check whether tag listing is supported for the specified file
  663. function! s:Tlist_Skip_File(filename, ftype)
  664. " Skip buffers with no names and buffers with filetype not set
  665. if a:filename == '' || a:ftype == ''
  666. return 1
  667. endif
  668. " Skip files which are not supported by exuberant ctags
  669. " First check whether default settings for this filetype are available.
  670. " If it is not available, then check whether user specified settings are
  671. " available. If both are not available, then don't list the tags for this
  672. " filetype
  673. let var = 's:tlist_def_' . a:ftype . '_settings'
  674. if !exists(var)
  675. let var = 'g:tlist_' . a:ftype . '_settings'
  676. if !exists(var)
  677. return 1
  678. endif
  679. endif
  680. " Skip files which are not readable or files which are not yet stored
  681. " to the disk
  682. if !filereadable(a:filename)
  683. return 1
  684. endif
  685. return 0
  686. endfunction
  687. " Tlist_User_Removed_File
  688. " Returns 1 if a file is removed by a user from the taglist
  689. function! s:Tlist_User_Removed_File(filename)
  690. return stridx(s:tlist_removed_flist, a:filename . "\n") != -1
  691. endfunction
  692. " Tlist_Update_Remove_List
  693. " Update the list of user removed files from the taglist
  694. " add == 1, add the file to the removed list
  695. " add == 0, delete the file from the removed list
  696. function! s:Tlist_Update_Remove_List(filename, add)
  697. if a:add
  698. let s:tlist_removed_flist = s:tlist_removed_flist . a:filename . "\n"
  699. else
  700. let idx = stridx(s:tlist_removed_flist, a:filename . "\n")
  701. let text_before = strpart(s:tlist_removed_flist, 0, idx)
  702. let rem_text = strpart(s:tlist_removed_flist, idx)
  703. let next_idx = stridx(rem_text, "\n")
  704. let text_after = strpart(rem_text, next_idx + 1)
  705. let s:tlist_removed_flist = text_before . text_after
  706. endif
  707. endfunction
  708. " Tlist_FileType_Init
  709. " Initialize the ctags arguments and tag variable for the specified
  710. " file type
  711. function! s:Tlist_FileType_Init(ftype)
  712. call s:Tlist_Log_Msg('Tlist_FileType_Init (' . a:ftype . ')')
  713. " If the user didn't specify any settings, then use the default
  714. " ctags args. Otherwise, use the settings specified by the user
  715. let var = 'g:tlist_' . a:ftype . '_settings'
  716. if exists(var)
  717. " User specified ctags arguments
  718. let settings = {var} . ';'
  719. else
  720. " Default ctags arguments
  721. let var = 's:tlist_def_' . a:ftype . '_settings'
  722. if !exists(var)
  723. " No default settings for this file type. This filetype is
  724. " not supported
  725. return 0
  726. endif
  727. let settings = s:tlist_def_{a:ftype}_settings . ';'
  728. endif
  729. let msg = 'Taglist: Invalid ctags option setting - ' . settings
  730. " Format of the option that specifies the filetype and ctags arugments:
  731. "
  732. " <language_name>;flag1:name1;flag2:name2;flag3:name3
  733. "
  734. " Extract the file type to pass to ctags. This may be different from the
  735. " file type detected by Vim
  736. let pos = stridx(settings, ';')
  737. if pos == -1
  738. call s:Tlist_Warning_Msg(msg)
  739. return 0
  740. endif
  741. let ctags_ftype = strpart(settings, 0, pos)
  742. if ctags_ftype == ''
  743. call s:Tlist_Warning_Msg(msg)
  744. return 0
  745. endif
  746. " Make sure a valid filetype is supplied. If the user didn't specify a
  747. " valid filetype, then the ctags option settings may be treated as the
  748. " filetype
  749. if ctags_ftype =~ ':'
  750. call s:Tlist_Warning_Msg(msg)
  751. return 0
  752. endif
  753. " Remove the file type from settings
  754. let settings = strpart(settings, pos + 1)
  755. if settings == ''
  756. call s:Tlist_Warning_Msg(msg)
  757. return 0
  758. endif
  759. " Process all the specified ctags flags. The format is
  760. " flag1:name1;flag2:name2;flag3:name3
  761. let ctags_flags = ''
  762. let cnt = 0
  763. while settings != ''
  764. " Extract the flag
  765. let pos = stridx(settings, ':')
  766. if pos == -1
  767. call s:Tlist_Warning_Msg(msg)
  768. return 0
  769. endif
  770. let flag = strpart(settings, 0, pos)
  771. if flag == ''
  772. call s:Tlist_Warning_Msg(msg)
  773. return 0
  774. endif
  775. " Remove the flag from settings
  776. let settings = strpart(settings, pos + 1)
  777. " Extract the tag type name
  778. let pos = stridx(settings, ';')
  779. if pos == -1
  780. call s:Tlist_Warning_Msg(msg)
  781. return 0
  782. endif
  783. let name = strpart(settings, 0, pos)
  784. if name == ''
  785. call s:Tlist_Warning_Msg(msg)
  786. return 0
  787. endif
  788. let settings = strpart(settings, pos + 1)
  789. let cnt = cnt + 1
  790. let s:tlist_{a:ftype}_{cnt}_name = flag
  791. let s:tlist_{a:ftype}_{cnt}_fullname = name
  792. let ctags_flags = ctags_flags . flag
  793. endwhile
  794. let s:tlist_{a:ftype}_ctags_args = '--language-force=' . ctags_ftype .
  795. \ ' --' . ctags_ftype . '-types=' . ctags_flags
  796. let s:tlist_{a:ftype}_count = cnt
  797. let s:tlist_{a:ftype}_ctags_flags = ctags_flags
  798. " Save the filetype name
  799. let s:tlist_ftype_{s:tlist_ftype_count}_name = a:ftype
  800. let s:tlist_ftype_count = s:tlist_ftype_count + 1
  801. return 1
  802. endfunction
  803. " Tlist_Detect_Filetype
  804. " Determine the filetype for the specified file using the filetypedetect
  805. " autocmd.
  806. function! s:Tlist_Detect_Filetype(fname)
  807. " Ignore the filetype autocommands
  808. let old_eventignore = &eventignore
  809. set eventignore=FileType
  810. " Save the 'filetype', as this will be changed temporarily
  811. let old_filetype = &filetype
  812. " Run the filetypedetect group of autocommands to determine
  813. " the filetype
  814. exe 'doautocmd filetypedetect BufRead ' . a:fname
  815. " Save the detected filetype
  816. let ftype = &filetype
  817. " Restore the previous state
  818. let &filetype = old_filetype
  819. let &eventignore = old_eventignore
  820. return ftype
  821. endfunction
  822. " Tlist_Get_Buffer_Filetype
  823. " Get the filetype for the specified buffer
  824. function! s:Tlist_Get_Buffer_Filetype(bnum)
  825. let buf_ft = getbufvar(a:bnum, '&filetype')
  826. if bufloaded(a:bnum)
  827. " For loaded buffers, the 'filetype' is already determined
  828. return buf_ft
  829. endif
  830. " For unloaded buffers, if the 'filetype' option is set, return it
  831. if buf_ft != ''
  832. return buf_ft
  833. endif
  834. " Skip non-existent buffers
  835. if !bufexists(a:bnum)
  836. return ''
  837. endif
  838. " For buffers whose filetype is not yet determined, try to determine
  839. " the filetype
  840. let bname = bufname(a:bnum)
  841. return s:Tlist_Detect_Filetype(bname)
  842. endfunction
  843. " Tlist_Discard_TagInfo
  844. " Discard the stored tag information for a file
  845. function! s:Tlist_Discard_TagInfo(fidx)
  846. call s:Tlist_Log_Msg('Tlist_Discard_TagInfo (' .
  847. \ s:tlist_{a:fidx}_filename . ')')
  848. let ftype = s:tlist_{a:fidx}_filetype
  849. " Discard information about the tags defined in the file
  850. let i = 1
  851. while i <= s:tlist_{a:fidx}_tag_count
  852. let fidx_i = 's:tlist_' . a:fidx . '_' . i
  853. unlet! {fidx_i}_tag
  854. unlet! {fidx_i}_tag_name
  855. unlet! {fidx_i}_tag_type
  856. unlet! {fidx_i}_ttype_idx
  857. unlet! {fidx_i}_tag_proto
  858. unlet! {fidx_i}_tag_searchpat
  859. unlet! {fidx_i}_tag_linenum
  860. let i = i + 1
  861. endwhile
  862. let s:tlist_{a:fidx}_tag_count = 0
  863. " Discard information about tag type groups
  864. let i = 1
  865. while i <= s:tlist_{ftype}_count
  866. let ttype = s:tlist_{ftype}_{i}_name
  867. if s:tlist_{a:fidx}_{ttype} != ''
  868. let fidx_ttype = 's:tlist_' . a:fidx . '_' . ttype
  869. let {fidx_ttype} = ''
  870. let {fidx_ttype}_offset = 0
  871. let cnt = {fidx_ttype}_count
  872. let {fidx_ttype}_count = 0
  873. let j = 1
  874. while j <= cnt
  875. unlet! {fidx_ttype}_{j}
  876. let j = j + 1
  877. endwhile
  878. endif
  879. let i = i + 1
  880. endwhile
  881. " Discard the stored menu command also
  882. let s:tlist_{a:fidx}_menu_cmd = ''
  883. endfunction
  884. " Tlist_Window_Update_Line_Offsets
  885. " Update the line offsets for tags for files starting from start_idx
  886. " and displayed in the taglist window by the specified offset
  887. function! s:Tlist_Window_Update_Line_Offsets(start_idx, increment, offset)
  888. let i = a:start_idx
  889. while i < s:tlist_file_count
  890. if s:tlist_{i}_visible
  891. " Update the start/end line number only if the file is visible
  892. if a:increment
  893. let s:tlist_{i}_start = s:tlist_{i}_start + a:offset
  894. let s:tlist_{i}_end = s:tlist_{i}_end + a:offset
  895. else
  896. let s:tlist_{i}_start = s:tlist_{i}_start - a:offset
  897. let s:tlist_{i}_end = s:tlist_{i}_end - a:offset
  898. endif
  899. endif
  900. let i = i + 1
  901. endwhile
  902. endfunction
  903. " Tlist_Discard_FileInfo
  904. " Discard the stored information for a file
  905. function! s:Tlist_Discard_FileInfo(fidx)
  906. call s:Tlist_Log_Msg('Tlist_Discard_FileInfo (' .
  907. \ s:tlist_{a:fidx}_filename . ')')
  908. call s:Tlist_Discard_TagInfo(a:fidx)
  909. let ftype = s:tlist_{a:fidx}_filetype
  910. let i = 1
  911. while i <= s:tlist_{ftype}_count
  912. let ttype = s:tlist_{ftype}_{i}_name
  913. unlet! s:tlist_{a:fidx}_{ttype}
  914. unlet! s:tlist_{a:fidx}_{ttype}_offset
  915. unlet! s:tlist_{a:fidx}_{ttype}_count
  916. let i = i + 1
  917. endwhile
  918. unlet! s:tlist_{a:fidx}_filename
  919. unlet! s:tlist_{a:fidx}_sort_type
  920. unlet! s:tlist_{a:fidx}_filetype
  921. unlet! s:tlist_{a:fidx}_mtime
  922. unlet! s:tlist_{a:fidx}_start
  923. unlet! s:tlist_{a:fidx}_end
  924. unlet! s:tlist_{a:fidx}_valid
  925. unlet! s:tlist_{a:fidx}_visible
  926. unlet! s:tlist_{a:fidx}_tag_count
  927. unlet! s:tlist_{a:fidx}_menu_cmd
  928. endfunction
  929. " Tlist_Window_Remove_File_From_Display
  930. " Remove the specified file from display
  931. function! s:Tlist_Window_Remove_File_From_Display(fidx)
  932. call s:Tlist_Log_Msg('Tlist_Window_Remove_File_From_Display (' .
  933. \ s:tlist_{a:fidx}_filename . ')')
  934. " If the file is not visible then no need to remove it
  935. if !s:tlist_{a:fidx}_visible
  936. return
  937. endif
  938. " Remove the tags displayed for the specified file from the window
  939. let start = s:tlist_{a:fidx}_start
  940. " Include the empty line after the last line also
  941. if g:Tlist_Compact_Format
  942. let end = s:tlist_{a:fidx}_end
  943. else
  944. let end = s:tlist_{a:fidx}_end + 1
  945. endif
  946. setlocal modifiable
  947. exe 'silent! ' . start . ',' . end . 'delete _'
  948. setlocal nomodifiable
  949. " Correct the start and end line offsets for all the files following
  950. " this file, as the tags for this file are removed
  951. call s:Tlist_Window_Update_Line_Offsets(a:fidx + 1, 0, end - start + 1)
  952. endfunction
  953. " Tlist_Remove_File
  954. " Remove the file under the cursor or the specified file index
  955. " user_request - User requested to remove the file from taglist
  956. function! s:Tlist_Remove_File(file_idx, user_request)
  957. let fidx = a:file_idx
  958. if fidx == -1
  959. let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
  960. if fidx == -1
  961. return
  962. endif
  963. endif
  964. call s:Tlist_Log_Msg('Tlist_Remove_File (' .
  965. \ s:tlist_{fidx}_filename . ', ' . a:user_request . ')')
  966. let save_winnr = winnr()
  967. let winnum = bufwinnr(g:TagList_title)
  968. if winnum != -1
  969. " Taglist window is open, remove the file from display
  970. if save_winnr != winnum
  971. let old_eventignore = &eventignore
  972. set eventignore=all
  973. exe winnum . 'wincmd w'
  974. endif
  975. call s:Tlist_Window_Remove_File_From_Display(fidx)
  976. if save_winnr != winnum
  977. exe save_winnr . 'wincmd w'
  978. let &eventignore = old_eventignore
  979. endif
  980. endif
  981. let fname = s:tlist_{fidx}_filename
  982. if a:user_request
  983. " As the user requested to remove the file from taglist,
  984. " add it to the removed list
  985. call s:Tlist_Update_Remove_List(fname, 1)
  986. endif
  987. " Remove the file name from the taglist list of filenames
  988. let idx = stridx(s:tlist_file_names, fname . "\n")
  989. let text_before = strpart(s:tlist_file_names, 0, idx)
  990. let rem_text = strpart(s:tlist_file_names, idx)
  991. let next_idx = stridx(rem_text, "\n")
  992. let text_after = strpart(rem_text, next_idx + 1)
  993. let s:tlist_file_names = text_before . text_after
  994. call s:Tlist_Discard_FileInfo(fidx)
  995. " Shift all the file variables by one index
  996. let i = fidx + 1
  997. while i < s:tlist_file_count
  998. let j = i - 1
  999. let s:tlist_{j}_filename = s:tlist_{i}_filename
  1000. let s:tlist_{j}_sort_type = s:tlist_{i}_sort_type
  1001. let s:tlist_{j}_filetype = s:tlist_{i}_filetype
  1002. let s:tlist_{j}_mtime = s:tlist_{i}_mtime
  1003. let s:tlist_{j}_start = s:tlist_{i}_start
  1004. let s:tlist_{j}_end = s:tlist_{i}_end
  1005. let s:tlist_{j}_valid = s:tlist_{i}_valid
  1006. let s:tlist_{j}_visible = s:tlist_{i}_visible
  1007. let s:tlist_{j}_tag_count = s:tlist_{i}_tag_count
  1008. let s:tlist_{j}_menu_cmd = s:tlist_{i}_menu_cmd
  1009. let k = 1
  1010. while k <= s:tlist_{j}_tag_count
  1011. let s:tlist_{j}_{k}_tag = s:tlist_{i}_{k}_tag
  1012. let s:tlist_{j}_{k}_tag_name = s:tlist_{i}_{k}_tag_name
  1013. let s:tlist_{j}_{k}_tag_type = s:Tlist_Get_Tag_Type_By_Tag(i, k)
  1014. let s:tlist_{j}_{k}_ttype_idx = s:tlist_{i}_{k}_ttype_idx
  1015. let s:tlist_{j}_{k}_tag_proto = s:Tlist_Get_Tag_Prototype(i, k)
  1016. let s:tlist_{j}_{k}_tag_searchpat = s:Tlist_Get_Tag_SearchPat(i, k)
  1017. let s:tlist_{j}_{k}_tag_linenum = s:Tlist_Get_Tag_Linenum(i, k)
  1018. let k = k + 1
  1019. endwhile
  1020. let ftype = s:tlist_{i}_filetype
  1021. let k = 1
  1022. while k <= s:tlist_{ftype}_count
  1023. let ttype = s:tlist_{ftype}_{k}_name
  1024. let s:tlist_{j}_{ttype} = s:tlist_{i}_{ttype}
  1025. let s:tlist_{j}_{ttype}_offset = s:tlist_{i}_{ttype}_offset
  1026. let s:tlist_{j}_{ttype}_count = s:tlist_{i}_{ttype}_count
  1027. if s:tlist_{j}_{ttype} != ''
  1028. let l = 1
  1029. while l <= s:tlist_{j}_{ttype}_count
  1030. let s:tlist_{j}_{ttype}_{l} = s:tlist_{i}_{ttype}_{l}
  1031. let l = l + 1
  1032. endwhile
  1033. endif
  1034. let k = k + 1
  1035. endwhile
  1036. " As the file and tag information is copied to the new index,
  1037. " discard the previous information
  1038. call s:Tlist_Discard_FileInfo(i)
  1039. let i = i + 1
  1040. endwhile
  1041. " Reduce the number of files displayed
  1042. let s:tlist_file_count = s:tlist_file_count - 1
  1043. if g:Tlist_Show_One_File
  1044. " If the tags for only one file is displayed and if we just
  1045. " now removed that file, then invalidate the current file idx
  1046. if s:tlist_cur_file_idx == fidx
  1047. let s:tlist_cur_file_idx = -1
  1048. endif
  1049. endif
  1050. endfunction
  1051. " Tlist_Window_Goto_Window
  1052. " Goto the taglist window
  1053. function! s:Tlist_Window_Goto_Window()
  1054. let winnum = bufwinnr(g:TagList_title)
  1055. if winnum != -1
  1056. if winnr() != winnum
  1057. call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
  1058. endif
  1059. endif
  1060. endfunction
  1061. " Tlist_Window_Create
  1062. " Create a new taglist window. If it is already open, jump to it
  1063. function! s:Tlist_Window_Create()
  1064. call s:Tlist_Log_Msg('Tlist_Window_Create()')
  1065. " If the window is open, jump to it
  1066. let winnum = bufwinnr(g:TagList_title)
  1067. if winnum != -1
  1068. " Jump to the existing window
  1069. if winnr() != winnum
  1070. exe winnum . 'wincmd w'
  1071. endif
  1072. return
  1073. endif
  1074. " If used with winmanager don't open windows. Winmanager will handle
  1075. " the window/buffer management
  1076. if s:tlist_app_name == "winmanager"
  1077. return
  1078. endif
  1079. " Create a new window. If user prefers a horizontal window, then open
  1080. " a horizontally split window. Otherwise open a vertically split
  1081. " window
  1082. if g:Tlist_Use_Horiz_Window
  1083. " Open a horizontally split window
  1084. let win_dir = 'botright'
  1085. " Horizontal window height
  1086. let win_size = g:Tlist_WinHeight
  1087. else
  1088. if s:tlist_winsize_chgd == -1
  1089. " Open a vertically split window. Increase the window size, if
  1090. " needed, to accomodate the new window
  1091. if g:Tlist_Inc_Winwidth &&
  1092. \ &columns < (80 + g:Tlist_WinWidth)
  1093. " Save the original window position
  1094. let s:tlist_pre_winx = getwinposx()
  1095. let s:tlist_pre_winy = getwinposy()
  1096. " one extra column is needed to include the vertical split
  1097. let &columns= &columns + g:Tlist_WinWidth + 1
  1098. let s:tlist_winsize_chgd = 1
  1099. else
  1100. let s:tlist_winsize_chgd = 0
  1101. endif
  1102. endif
  1103. if g:Tlist_Use_Right_Window
  1104. " Open the window at the rightmost place
  1105. let win_dir = 'botright vertical'
  1106. else
  1107. " Open the window at the leftmost place
  1108. let win_dir = 'topleft vertical'
  1109. endif
  1110. let win_size = g:Tlist_WinWidth
  1111. endif
  1112. " If the tag listing temporary buffer already exists, then reuse it.
  1113. " Otherwise create a new buffer
  1114. let bufnum = bufnr(g:TagList_title)
  1115. if bufnum == -1
  1116. " Create a new buffer
  1117. let wcmd = g:TagList_title
  1118. else
  1119. " Edit the existing buffer
  1120. let wcmd = '+buffer' . bufnum
  1121. endif
  1122. " Create the taglist window
  1123. exe 'silent! ' . win_dir . ' ' . win_size . 'split ' . wcmd
  1124. " Save the new window position
  1125. let s:tlist_winx = getwinposx()
  1126. let s:tlist_winy = getwinposy()
  1127. " Initialize the taglist window
  1128. call s:Tlist_Window_Init()
  1129. endfunction
  1130. " Tlist_Window_Zoom
  1131. " Zoom (maximize/minimize) the taglist window
  1132. function! s:Tlist_Window_Zoom()
  1133. if s:tlist_win_maximized
  1134. " Restore the window back to the previous size
  1135. if g:Tlist_Use_Horiz_Window
  1136. exe 'resize ' . g:Tlist_WinHeight
  1137. else
  1138. exe 'vert resize ' . g:Tlist_WinWidth
  1139. endif
  1140. let s:tlist_win_maximized = 0
  1141. else
  1142. " Set the window size to the maximum possible without closing other
  1143. " windows
  1144. if g:Tlist_Use_Horiz_Window
  1145. resize
  1146. else
  1147. vert resize
  1148. endif
  1149. let s:tlist_win_maximized = 1
  1150. endif
  1151. endfunction
  1152. " Tlist_Ballon_Expr
  1153. " When the mouse cursor is over a tag in the taglist window, display the
  1154. " tag prototype (balloon)
  1155. function! Tlist_Ballon_Expr()
  1156. " Get the file index
  1157. let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(v:beval_lnum)
  1158. if fidx == -1
  1159. return ''
  1160. endif
  1161. " Get the tag output line for the current tag
  1162. let tidx = s:Tlist_Window_Get_Tag_Index(fidx, v:beval_lnum)
  1163. if tidx == 0
  1164. return ''
  1165. endif
  1166. " Get the tag search pattern and display it
  1167. return s:Tlist_Get_Tag_Prototype(fidx, tidx)
  1168. endfunction
  1169. " Tlist_Window_Check_Width
  1170. " Check the width of the taglist window. For horizontally split windows, the
  1171. " 'winfixheight' option is used to fix the height of the window. For
  1172. " vertically split windows, Vim doesn't support the 'winfixwidth' option. So
  1173. " need to handle window width changes from this function.
  1174. function! s:Tlist_Window_Check_Width()
  1175. let tlist_winnr = bufwinnr(g:TagList_title)
  1176. if tlist_winnr == -1
  1177. return
  1178. endif
  1179. let width = winwidth(tlist_winnr)
  1180. if width != g:Tlist_WinWidth
  1181. call s:Tlist_Log_Msg("Tlist_Window_Check_Width: Changing window " .
  1182. \ "width from " . width . " to " . g:Tlist_WinWidth)
  1183. let save_winnr = winnr()
  1184. if save_winnr != tlist_winnr
  1185. call s:Tlist_Exe_Cmd_No_Acmds(tlist_winnr . 'wincmd w')
  1186. endif
  1187. exe 'vert resize ' . g:Tlist_WinWidth
  1188. if save_winnr != tlist_winnr
  1189. call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
  1190. endif
  1191. endif
  1192. endfunction
  1193. " Tlist_Window_Exit_Only_Window
  1194. " If the 'Tlist_Exit_OnlyWindow' option is set, then exit Vim if only the
  1195. " taglist window is present.
  1196. function! s:Tlist_Window_Exit_Only_Window()
  1197. " Before quitting Vim, delete the taglist buffer so that
  1198. " the '0 mark is correctly set to the previous buffer.
  1199. if v:version < 700
  1200. if winbufnr(2) == -1
  1201. bdelete
  1202. quit
  1203. endif
  1204. else
  1205. if winbufnr(2) == -1
  1206. if tabpagenr('$') == 1
  1207. " Only one tag page is present
  1208. bdelete
  1209. quit
  1210. else
  1211. " More than one tab page is present. Close only the current
  1212. " tab page
  1213. close
  1214. endif
  1215. endif
  1216. endif
  1217. endfunction
  1218. " Tlist_Window_Init
  1219. " Set the default options for the taglist window
  1220. function! s:Tlist_Window_Init()
  1221. call s:Tlist_Log_Msg('Tlist_Window_Init()')
  1222. " The 'readonly' option should not be set for the taglist buffer.
  1223. " If Vim is started as "view/gview" or if the ":view" command is
  1224. " used, then the 'readonly' option is set for all the buffers.
  1225. " Unset it for the taglist buffer
  1226. setlocal noreadonly
  1227. " Set the taglist buffer filetype to taglist
  1228. setlocal filetype=taglist
  1229. " Define taglist window element highlighting
  1230. syntax match TagListComment '^" .*'
  1231. syntax match TagListFileName '^[^" ].*$'
  1232. syntax match TagListTitle '^ \S.*$'
  1233. syntax match TagListTagScope '\s\[.\{-\}\]$'
  1234. " Define the highlighting only if colors are supported
  1235. if has('gui_running') || &t_Co > 2
  1236. " Colors to highlight various taglist window elements
  1237. " If user defined highlighting group exists, then use them.
  1238. " Otherwise, use default highlight groups.
  1239. if hlexists('MyTagListTagName')
  1240. highlight link TagListTagName MyTagListTagName
  1241. else
  1242. highlight default link TagListTagName Search
  1243. endif
  1244. " Colors to highlight comments and titles
  1245. if hlexists('MyTagListComment')
  1246. highlight link TagListComment MyTagListComment
  1247. else
  1248. highlight clear TagListComment
  1249. highlight default link TagListComment Comment
  1250. endif
  1251. if hlexists('MyTagListTitle')
  1252. highlight link TagListTitle MyTagListTitle
  1253. else
  1254. highlight clear TagListTitle
  1255. highlight default link TagListTitle Title
  1256. endif
  1257. if hlexists('MyTagListFileName')
  1258. highlight link TagListFileName MyTagListFileName
  1259. else
  1260. highlight clear TagListFileName
  1261. highlight default TagListFileName guibg=Grey ctermbg=darkgray
  1262. \ guifg=white ctermfg=white
  1263. endif
  1264. if hlexists('MyTagListTagScope')
  1265. highlight link TagListTagScope MyTagListTagScope
  1266. else
  1267. highlight clear TagListTagScope
  1268. highlight default link TagListTagScope Identifier
  1269. endif
  1270. else
  1271. highlight default TagListTagName term=reverse cterm=reverse
  1272. endif
  1273. " Folding related settings
  1274. setlocal foldenable
  1275. setlocal foldminlines=0
  1276. setlocal foldmethod=manual
  1277. setlocal foldlevel=9999
  1278. if g:Tlist_Enable_Fold_Column
  1279. setlocal foldcolumn=3
  1280. else
  1281. setlocal foldcolumn=0
  1282. endif
  1283. setlocal foldtext=v:folddashes.getline(v:foldstart)
  1284. if s:tlist_app_name != "winmanager"
  1285. " Mark buffer as scratch
  1286. silent! setlocal buftype=nofile
  1287. if s:tlist_app_name == "none"
  1288. silent! setlocal bufhidden=delete
  1289. endif
  1290. silent! setlocal noswapfile
  1291. " Due to a bug in Vim 6.0, the winbufnr() function fails for unlisted
  1292. " buffers. So if the taglist buffer is unlisted, multiple taglist
  1293. " windows will be opened. This bug is fixed in Vim 6.1 and above
  1294. if v:version >= 601
  1295. silent! setlocal nobuflisted
  1296. endif
  1297. endif
  1298. silent! setlocal nowrap
  1299. " If the 'number' option is set in the source window, it will affect the
  1300. " taglist window. So forcefully disable 'number' option for the taglist
  1301. " window
  1302. silent! setlocal nonumber
  1303. " Use fixed height when horizontally split window is used
  1304. if g:Tlist_Use_Horiz_Window
  1305. if v:version >= 602
  1306. set winfixheight
  1307. endif
  1308. endif
  1309. if !g:Tlist_Use_Horiz_Window && v:version >= 700
  1310. set winfixwidth
  1311. endif
  1312. " Setup balloon evaluation to display tag prototype
  1313. if v:version >= 700 && has('balloon_eval')
  1314. setlocal balloonexpr=Tlist_Ballon_Expr()
  1315. set ballooneval
  1316. endif
  1317. " Setup the cpoptions properly for the maps to work
  1318. let old_cpoptions = &cpoptions
  1319. set cpoptions&vim
  1320. " Create buffer local mappings for jumping to the tags and sorting the list
  1321. nnoremap <buffer> <silent> <CR>
  1322. \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
  1323. nnoremap <buffer> <silent> o
  1324. \ :call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
  1325. nnoremap <buffer> <silent> p
  1326. \ :call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
  1327. nnoremap <buffer> <silent> P
  1328. \ :call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
  1329. if v:version >= 700
  1330. nnoremap <buffer> <silent> t
  1331. \ :call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
  1332. nnoremap <buffer> <silent> <C-t>
  1333. \ :call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
  1334. endif
  1335. nnoremap <buffer> <silent> <2-LeftMouse>
  1336. \ :call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
  1337. nnoremap <buffer> <silent> s
  1338. \ :call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
  1339. nnoremap <buffer> <silent> + :silent! foldopen<CR>
  1340. nnoremap <buffer> <silent> - :silent! foldclose<CR>
  1341. nnoremap <buffer> <silent> * :silent! %foldopen!<CR>
  1342. nnoremap <buffer> <silent> = :silent! %foldclose<CR>
  1343. nnoremap <buffer> <silent> <kPlus> :silent! foldopen<CR>
  1344. nnoremap <buffer> <silent> <kMinus> :silent! foldclose<CR>
  1345. nnoremap <buffer> <silent> <kMultiply> :silent! %foldopen!<CR>
  1346. nnoremap <buffer> <silent> <Space> :call <SID>Tlist_Window_Show_Info()<CR>
  1347. nnoremap <buffer> <silent> u :call <SID>Tlist_Window_Update_File()<CR>
  1348. nnoremap <buffer> <silent> d :call <SID>Tlist_Remove_File(-1, 1)<CR>
  1349. nnoremap <buffer> <silent> x :call <SID>Tlist_Window_Zoom()<CR>
  1350. nnoremap <buffer> <silent> [[ :call <SID>Tlist_Window_Move_To_File(-1)<CR>
  1351. nnoremap <buffer> <silent> <BS> :call <SID>Tlist_Window_Move_To_File(-1)<CR>
  1352. nnoremap <buffer> <silent> ]] :call <SID>Tlist_Window_Move_To_File(1)<CR>
  1353. nnoremap <buffer> <silent> <Tab> :call <SID>Tlist_Window_Move_To_File(1)<CR>
  1354. nnoremap <buffer> <silent> <F1> :call <SID>Tlist_Window_Toggle_Help_Text()<CR>
  1355. nnoremap <buffer> <silent> q :close<CR>
  1356. " Insert mode mappings
  1357. inoremap <buffer> <silent> <CR>
  1358. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
  1359. " Windows needs return
  1360. inoremap <buffer> <silent> <Return>
  1361. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
  1362. inoremap <buffer> <silent> o
  1363. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newwin')<CR>
  1364. inoremap <buffer> <silent> p
  1365. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('preview')<CR>
  1366. inoremap <buffer> <silent> P
  1367. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('prevwin')<CR>
  1368. if v:version >= 700
  1369. inoremap <buffer> <silent> t
  1370. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('checktab')<CR>
  1371. inoremap <buffer> <silent> <C-t>
  1372. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('newtab')<CR>
  1373. endif
  1374. inoremap <buffer> <silent> <2-LeftMouse>
  1375. \ <C-o>:call <SID>Tlist_Window_Jump_To_Tag('useopen')<CR>
  1376. inoremap <buffer> <silent> s
  1377. \ <C-o>:call <SID>Tlist_Change_Sort('cmd', 'toggle', '')<CR>
  1378. inoremap <buffer> <silent> + <C-o>:silent! foldopen<CR>
  1379. inoremap <buffer> <silent> - <C-o>:silent! foldclose<CR>
  1380. inoremap <buffer> <silent> * <C-o>:silent! %foldopen!<CR>
  1381. inoremap <buffer> <silent> = <C-o>:silent! %foldclose<CR>
  1382. inoremap <buffer> <silent> <kPlus> <C-o>:silent! foldopen<CR>
  1383. inoremap <buffer> <silent> <kMinus> <C-o>:silent! foldclose<CR>
  1384. inoremap <buffer> <silent> <kMultiply> <C-o>:silent! %foldopen!<CR>
  1385. inoremap <buffer> <silent> <Space> <C-o>:call
  1386. \ <SID>Tlist_Window_Show_Info()<CR>
  1387. inoremap <buffer> <silent> u
  1388. \ <C-o>:call <SID>Tlist_Window_Update_File()<CR>
  1389. inoremap <buffer> <silent> d <C-o>:call <SID>Tlist_Remove_File(-1, 1)<CR>
  1390. inoremap <buffer> <silent> x <C-o>:call <SID>Tlist_Window_Zoom()<CR>
  1391. inoremap <buffer> <silent> [[ <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
  1392. inoremap <buffer> <silent> <BS> <C-o>:call <SID>Tlist_Window_Move_To_File(-1)<CR>
  1393. inoremap <buffer> <silent> ]] <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
  1394. inoremap <buffer> <silent> <Tab> <C-o>:call <SID>Tlist_Window_Move_To_File(1)<CR>
  1395. inoremap <buffer> <silent> <F1> <C-o>:call <SID>Tlist_Window_Toggle_Help_Text()<CR>
  1396. inoremap <buffer> <silent> q <C-o>:close<CR>
  1397. " Map single left mouse click if the user wants this functionality
  1398. if g:Tlist_Use_SingleClick == 1
  1399. " Contributed by Bindu Wavell
  1400. " attempt to perform single click mapping, it would be much
  1401. " nicer if we could nnoremap <buffer> ... however vim does
  1402. " not fire the <buffer> <leftmouse> when you use the mouse
  1403. " to enter a buffer.
  1404. let clickmap = ':if bufname("%") =~ "__Tag_List__" <bar> ' .
  1405. \ 'call <SID>Tlist_Window_Jump_To_Tag("useopen") ' .
  1406. \ '<bar> endif <CR>'
  1407. if maparg('<leftmouse>', 'n') == ''
  1408. " no mapping for leftmouse
  1409. exe ':nnoremap <silent> <leftmouse> <leftmouse>' . clickmap
  1410. else
  1411. " we have a mapping
  1412. let mapcmd = ':nnoremap <silent> <leftmouse> <leftmouse>'
  1413. let mapcmd = mapcmd . substitute(substitute(
  1414. \ maparg('<leftmouse>', 'n'), '|', '<bar>', 'g'),
  1415. \ '\c^<leftmouse>', '', '')
  1416. let mapcmd = mapcmd . clickmap
  1417. exe mapcmd
  1418. endif
  1419. endif
  1420. " Define the taglist autocommands
  1421. augroup TagListAutoCmds
  1422. autocmd!
  1423. " Display the tag prototype for the tag under the cursor.
  1424. autocmd CursorHold __Tag_List__ call s:Tlist_Window_Show_Info()
  1425. " Highlight the current tag periodically
  1426. autocmd CursorHold * silent call s:Tlist_Window_Highlight_Tag(
  1427. \ fnamemodify(bufname('%'), ':p'), line('.'), 1, 0)
  1428. " Adjust the Vim window width when taglist window is closed
  1429. autocmd BufUnload __Tag_List__ call s:Tlist_Post_Close_Cleanup()
  1430. " Close the fold for this buffer when leaving the buffer
  1431. if g:Tlist_File_Fold_Auto_Close
  1432. autocmd BufEnter * silent
  1433. \ call s:Tlist_Window_Open_File_Fold(expand('<abuf>'))
  1434. endif
  1435. " Exit Vim itself if only the taglist window is present (optional)
  1436. if g:Tlist_Exit_OnlyWindow
  1437. autocmd BufEnter __Tag_List__ nested
  1438. \ call s:Tlist_Window_Exit_Only_Window()
  1439. endif
  1440. if s:tlist_app_name != "winmanager" &&
  1441. \ !g:Tlist_Process_File_Always &&
  1442. \ (!has('gui_running') || !g:Tlist_Show_Menu)
  1443. " Auto refresh the taglist window
  1444. autocmd BufEnter * call s:Tlist_Refresh()
  1445. endif
  1446. if !g:Tlist_Use_Horiz_Window
  1447. if v:version < 700
  1448. autocmd WinEnter * call s:Tlist_Window_Check_Width()
  1449. endif
  1450. endif
  1451. if v:version >= 700
  1452. autocmd TabEnter * silent call s:Tlist_Refresh_Folds()
  1453. endif
  1454. augroup end
  1455. " Restore the previous cpoptions settings
  1456. let &cpoptions = old_cpoptions
  1457. endfunction
  1458. " Tlist_Window_Refresh
  1459. " Display the tags for all the files in the taglist window
  1460. function! s:Tlist_Window_Refresh()
  1461. call s:Tlist_Log_Msg('Tlist_Window_Refresh()')
  1462. " Set report option to a huge value to prevent informational messages
  1463. " while deleting the lines
  1464. let old_report = &report
  1465. set report=99999
  1466. " Mark the buffer as modifiable
  1467. setlocal modifiable
  1468. " Delete the contents of the buffer to the black-hole register
  1469. silent! %delete _
  1470. " As we have cleared the taglist window, mark all the files
  1471. " as not visible
  1472. let i = 0
  1473. while i < s:tlist_file_count
  1474. let s:tlist_{i}_visible = 0
  1475. let i = i + 1
  1476. endwhile
  1477. if g:Tlist_Compact_Format == 0
  1478. " Display help in non-compact mode
  1479. call s:Tlist_Window_Display_Help()
  1480. endif
  1481. " Mark the buffer as not modifiable
  1482. setlocal nomodifiable
  1483. " Restore the report option
  1484. let &report = old_report
  1485. " If the tags for only one file should be displayed in the taglist
  1486. " window, then no need to add the tags here. The bufenter autocommand
  1487. " will add the tags for that file.
  1488. if g:Tlist_Show_One_File
  1489. return
  1490. endif
  1491. " List all the tags for the previously processed files
  1492. " Do this only if taglist is configured to display tags for more than
  1493. " one file. Otherwise, when Tlist_Show_One_File is configured,
  1494. " tags for the wrong file will be displayed.
  1495. let i = 0
  1496. while i < s:tlist_file_count
  1497. call s:Tlist_Window_Refresh_File(s:tlist_{i}_filename,
  1498. \ s:tlist_{i}_filetype)
  1499. let i = i + 1
  1500. endwhile
  1501. if g:Tlist_Auto_Update
  1502. " Add and list the tags for all buffers in the Vim buffer list
  1503. let i = 1
  1504. let last_bufnum = bufnr('$')
  1505. while i <= last_bufnum
  1506. if buflisted(i)
  1507. let fname = fnamemodify(bufname(i), ':p')
  1508. let ftype = s:Tlist_Get_Buffer_Filetype(i)
  1509. " If the file doesn't support tag listing, skip it
  1510. if !s:Tlist_Skip_File(fname, ftype)
  1511. call s:Tlist_Window_Refresh_File(fname, ftype)
  1512. endif
  1513. endif
  1514. let i = i + 1
  1515. endwhile
  1516. endif
  1517. " If Tlist_File_Fold_Auto_Close option is set, then close all the folds
  1518. if g:Tlist_File_Fold_Auto_Close
  1519. " Close all the folds
  1520. silent! %foldclose
  1521. endif
  1522. " Move the cursor to the top of the taglist window
  1523. normal! gg
  1524. endfunction
  1525. " Tlist_Post_Close_Cleanup()
  1526. " Close the taglist window and adjust the Vim window width
  1527. function! s:Tlist_Post_Close_Cleanup()
  1528. call s:Tlist_Log_Msg('Tlist_Post_Close_Cleanup()')
  1529. " Mark all the files as not visible
  1530. let i = 0
  1531. while i < s:tlist_file_count
  1532. let s:tlist_{i}_visible = 0
  1533. let i = i + 1
  1534. endwhile
  1535. " Remove the taglist autocommands
  1536. silent! autocmd! TagListAutoCmds
  1537. " Clear all the highlights
  1538. match none
  1539. silent! syntax clear TagListTitle
  1540. silent! syntax clear TagListComment
  1541. silent! syntax clear TagListTagScope
  1542. " Remove the left mouse click mapping if it was setup initially
  1543. if g:Tlist_Use_SingleClick
  1544. if hasmapto('<LeftMouse>')
  1545. nunmap <LeftMouse>
  1546. endif
  1547. endif
  1548. if s:tlist_app_name != "winmanager"
  1549. if g:Tlist_Use_Horiz_Window || g:Tlist_Inc_Winwidth == 0 ||
  1550. \ s:tlist_winsize_chgd != 1 ||
  1551. \ &columns < (80 + g:Tlist_WinWidth)
  1552. " No need to adjust window width if using horizontally split taglist
  1553. " window or if columns is less than 101 or if the user chose not to
  1554. " adjust the window width
  1555. else
  1556. " If the user didn't manually move the window, then restore the window
  1557. " position to the pre-taglist position
  1558. if s:tlist_pre_winx != -1 && s:tlist_pre_winy != -1 &&
  1559. \ getwinposx() == s:tlist_winx &&
  1560. \ getwinposy() == s:tlist_winy
  1561. exe 'winpos ' . s:tlist_pre_winx . ' ' . s:tlist_pre_winy
  1562. endif
  1563. " Adjust the Vim window width
  1564. let &columns= &columns - (g:Tlist_WinWidth + 1)
  1565. endif
  1566. endif
  1567. let s:tlist_winsize_chgd = -1
  1568. " Reset taglist state variables
  1569. if s:tlist_app_name == "winmanager"
  1570. let s:tlist_app_name = "none"
  1571. endif
  1572. let s:tlist_window_initialized = 0
  1573. endfunction
  1574. " Tlist_Window_Refresh_File()
  1575. " List the tags defined in the specified file in a Vim window
  1576. function! s:Tlist_Window_Refresh_File(filename, ftype)
  1577. call s:Tlist_Log_Msg('Tlist_Window_Refresh_File (' . a:filename . ')')
  1578. " First check whether the file already exists
  1579. let fidx = s:Tlist_Get_File_Index(a:filename)
  1580. if fidx != -1
  1581. let file_listed = 1
  1582. else
  1583. let file_listed = 0
  1584. endif
  1585. if !file_listed
  1586. " Check whether this file is removed based on user request
  1587. " If it is, then don't display the tags for this file
  1588. if s:Tlist_User_Removed_File(a:filename)
  1589. return
  1590. endif
  1591. endif
  1592. if file_listed && s:tlist_{fidx}_visible
  1593. " Check whether the file tags are currently valid
  1594. if s:tlist_{fidx}_valid
  1595. " Goto the first line in the file
  1596. exe s:tlist_{fidx}_start
  1597. " If the line is inside a fold, open the fold
  1598. if foldclosed('.') != -1
  1599. exe "silent! " . s:tlist_{fidx}_start . "," .
  1600. \ s:tlist_{fidx}_end . "foldopen!"
  1601. endif
  1602. return
  1603. endif
  1604. " Discard and remove the tags for this file from display
  1605. call s:Tlist_Discard_TagInfo(fidx)
  1606. call s:Tlist_Window_Remove_File_From_Display(fidx)
  1607. endif
  1608. " Process and generate a list of tags defined in the file
  1609. if !file_listed || !s:tlist_{fidx}_valid
  1610. let ret_fidx = s:Tlist_Process_File(a:filename, a:ftype)
  1611. if ret_fidx == -1
  1612. return
  1613. endif
  1614. let fidx = ret_fidx
  1615. endif
  1616. " Set report option to a huge value to prevent informational messages
  1617. " while adding lines to the taglist window
  1618. let old_report = &report
  1619. set report=99999
  1620. if g:Tlist_Show_One_File
  1621. " Remove the previous file
  1622. if s:tlist_cur_file_idx != -1
  1623. call s:Tlist_Window_Remove_File_From_Display(s:tlist_cur_file_idx)
  1624. let s:tlist_{s:tlist_cur_file_idx}_visible = 0
  1625. let s:tlist_{s:tlist_cur_file_idx}_start = 0
  1626. let s:tlist_{s:tlist_cur_file_idx}_end = 0
  1627. endif
  1628. let s:tlist_cur_file_idx = fidx
  1629. endif
  1630. " Mark the buffer as modifiable
  1631. setlocal modifiable
  1632. " Add new files to the end of the window. For existing files, add them at
  1633. " the same line where they were previously present. If the file is not
  1634. " visible, then add it at the end
  1635. if s:tlist_{fidx}_start == 0 || !s:tlist_{fidx}_visible
  1636. if g:Tlist_Compact_Format
  1637. let s:tlist_{fidx}_start = line('$')
  1638. else
  1639. let s:tlist_{fidx}_start = line('$') + 1
  1640. endif
  1641. endif
  1642. let s:tlist_{fidx}_visible = 1
  1643. " Goto the line where this file should be placed
  1644. if g:Tlist_Compact_Format
  1645. exe s:tlist_{fidx}_start
  1646. else
  1647. exe s:tlist_{fidx}_start - 1
  1648. endif
  1649. let txt = fnamemodify(s:tlist_{fidx}_filename, ':t') . ' (' .
  1650. \ fnamemodify(s:tlist_{fidx}_filename, ':p:h') . ')'
  1651. if g:Tlist_Compact_Format == 0
  1652. silent! put =txt
  1653. else
  1654. silent! put! =txt
  1655. " Move to the next line
  1656. exe line('.') + 1
  1657. endif
  1658. let file_start = s:tlist_{fidx}_start
  1659. " Add the tag names grouped by tag type to the buffer with a title
  1660. let i = 1
  1661. let ttype_cnt = s:tlist_{a:ftype}_count
  1662. while i <= ttype_cnt
  1663. let ttype = s:tlist_{a:ftype}_{i}_name
  1664. " Add the tag type only if there are tags for that type
  1665. let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
  1666. let ttype_txt = {fidx_ttype}
  1667. if ttype_txt != ''
  1668. let txt = ' ' . s:tlist_{a:ftype}_{i}_fullname
  1669. if g:Tlist_Compact_Format == 0
  1670. let ttype_start_lnum = line('.') + 1
  1671. silent! put =txt
  1672. else
  1673. let ttype_start_lnum = line('.')
  1674. silent! put! =txt
  1675. endif
  1676. silent! put =ttype_txt
  1677. let {fidx_ttype}_offset = ttype_start_lnum - file_start
  1678. " create a fold for this tag type
  1679. let fold_start = ttype_start_lnum
  1680. let fold_end = fold_start + {fidx_ttype}_count
  1681. exe fold_start . ',' . fold_end . 'fold'
  1682. " Adjust the cursor position
  1683. if g:Tlist_Compact_Format == 0
  1684. exe ttype_start_lnum + {fidx_ttype}_count
  1685. else
  1686. exe ttype_start_lnum + {fidx_ttype}_count + 1
  1687. endif
  1688. if g:Tlist_Compact_Format == 0
  1689. " Separate the tag types by a empty line
  1690. silent! put =''
  1691. endif
  1692. endif
  1693. let i = i + 1
  1694. endwhile
  1695. if s:tlist_{fidx}_tag_count == 0
  1696. if g:Tlist_Compact_Format == 0
  1697. silent! put =''
  1698. endif
  1699. endif
  1700. let s:tlist_{fidx}_end = line('.') - 1
  1701. " Create a fold for the entire file
  1702. exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
  1703. exe 'silent! ' . s:tlist_{fidx}_start . ',' .
  1704. \ s:tlist_{fidx}_end . 'foldopen!'
  1705. " Goto the starting line for this file,
  1706. exe s:tlist_{fidx}_start
  1707. if s:tlist_app_name == "winmanager"
  1708. " To handle a bug in the winmanager plugin, add a space at the
  1709. " last line
  1710. call setline('$', ' ')
  1711. endif
  1712. " Mark the buffer as not modifiable
  1713. setlocal nomodifiable
  1714. " Restore the report option
  1715. let &report = old_report
  1716. " Update the start and end line numbers for all the files following this
  1717. " file
  1718. let start = s:tlist_{fidx}_start
  1719. " include the empty line after the last line
  1720. if g:Tlist_Compact_Format
  1721. let end = s:tlist_{fidx}_end
  1722. else
  1723. let end = s:tlist_{fidx}_end + 1
  1724. endif
  1725. call s:Tlist_Window_Update_Line_Offsets(fidx + 1, 1, end - start + 1)
  1726. " Now that we have updated the taglist window, update the tags
  1727. " menu (if present)
  1728. if g:Tlist_Show_Menu
  1729. call s:Tlist_Menu_Update_File(1)
  1730. endif
  1731. endfunction
  1732. " Tlist_Init_File
  1733. " Initialize the variables for a new file
  1734. function! s:Tlist_Init_File(filename, ftype)
  1735. call s:Tlist_Log_Msg('Tlist_Init_File (' . a:filename . ')')
  1736. " Add new files at the end of the list
  1737. let fidx = s:tlist_file_count
  1738. let s:tlist_file_count = s:tlist_file_count + 1
  1739. " Add the new file name to the taglist list of file names
  1740. let s:tlist_file_names = s:tlist_file_names . a:filename . "\n"
  1741. " Initialize the file variables
  1742. let s:tlist_{fidx}_filename = a:filename
  1743. let s:tlist_{fidx}_sort_type = g:Tlist_Sort_Type
  1744. let s:tlist_{fidx}_filetype = a:ftype
  1745. let s:tlist_{fidx}_mtime = -1
  1746. let s:tlist_{fidx}_start = 0
  1747. let s:tlist_{fidx}_end = 0
  1748. let s:tlist_{fidx}_valid = 0
  1749. let s:tlist_{fidx}_visible = 0
  1750. let s:tlist_{fidx}_tag_count = 0
  1751. let s:tlist_{fidx}_menu_cmd = ''
  1752. " Initialize the tag type variables
  1753. let i = 1
  1754. while i <= s:tlist_{a:ftype}_count
  1755. let ttype = s:tlist_{a:ftype}_{i}_name
  1756. let s:tlist_{fidx}_{ttype} = ''
  1757. let s:tlist_{fidx}_{ttype}_offset = 0
  1758. let s:tlist_{fidx}_{ttype}_count = 0
  1759. let i = i + 1
  1760. endwhile
  1761. return fidx
  1762. endfunction
  1763. " Tlist_Get_Tag_Type_By_Tag
  1764. " Return the tag type for the specified tag index
  1765. function! s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
  1766. let ttype_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_type'
  1767. " Already parsed and have the tag name
  1768. if exists(ttype_var)
  1769. return {ttype_var}
  1770. endif
  1771. let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
  1772. let {ttype_var} = s:Tlist_Extract_Tagtype(tag_line)
  1773. return {ttype_var}
  1774. endfunction
  1775. " Tlist_Get_Tag_Prototype
  1776. function! s:Tlist_Get_Tag_Prototype(fidx, tidx)
  1777. let tproto_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_proto'
  1778. " Already parsed and have the tag prototype
  1779. if exists(tproto_var)
  1780. return {tproto_var}
  1781. endif
  1782. " Parse and extract the tag prototype
  1783. let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
  1784. let start = stridx(tag_line, '/^') + 2
  1785. let end = stridx(tag_line, '/;"' . "\t")
  1786. if tag_line[end - 1] == '$'
  1787. let end = end -1
  1788. endif
  1789. let tag_proto = strpart(tag_line, start, end - start)
  1790. let {tproto_var} = substitute(tag_proto, '\s*', '', '')
  1791. return {tproto_var}
  1792. endfunction
  1793. " Tlist_Get_Tag_SearchPat
  1794. function! s:Tlist_Get_Tag_SearchPat(fidx, tidx)
  1795. let tpat_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_searchpat'
  1796. " Already parsed and have the tag search pattern
  1797. if exists(tpat_var)
  1798. return {tpat_var}
  1799. endif
  1800. " Parse and extract the tag search pattern
  1801. let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
  1802. let start = stridx(tag_line, '/^') + 2
  1803. let end = stridx(tag_line, '/;"' . "\t")
  1804. if tag_line[end - 1] == '$'
  1805. let end = end -1
  1806. endif
  1807. let {tpat_var} = '\V\^' . strpart(tag_line, start, end - start) .
  1808. \ (tag_line[end] == '$' ? '\$' : '')
  1809. return {tpat_var}
  1810. endfunction
  1811. " Tlist_Get_Tag_Linenum
  1812. " Return the tag line number, given the tag index
  1813. function! s:Tlist_Get_Tag_Linenum(fidx, tidx)
  1814. let tline_var = 's:tlist_' . a:fidx . '_' . a:tidx . '_tag_linenum'
  1815. " Already parsed and have the tag line number
  1816. if exists(tline_var)
  1817. return {tline_var}
  1818. endif
  1819. " Parse and extract the tag line number
  1820. let tag_line = s:tlist_{a:fidx}_{a:tidx}_tag
  1821. let start = strridx(tag_line, 'line:') + 5
  1822. let end = strridx(tag_line, "\t")
  1823. if end < start
  1824. let {tline_var} = strpart(tag_line, start) + 0
  1825. else
  1826. let {tline_var} = strpart(tag_line, start, end - start) + 0
  1827. endif
  1828. return {tline_var}
  1829. endfunction
  1830. " Tlist_Parse_Tagline
  1831. " Parse a tag line from the ctags output. Separate the tag output based on the
  1832. " tag type and store it in the tag type variable.
  1833. " The format of each line in the ctags output is:
  1834. "
  1835. " tag_name<TAB>file_name<TAB>ex_cmd;"<TAB>extension_fields
  1836. "
  1837. function! s:Tlist_Parse_Tagline(tag_line)
  1838. if a:tag_line == ''
  1839. " Skip empty lines
  1840. return
  1841. endif
  1842. " Extract the tag type
  1843. let ttype = s:Tlist_Extract_Tagtype(a:tag_line)
  1844. " Make sure the tag type is a valid and supported one
  1845. if ttype == '' || stridx(s:ctags_flags, ttype) == -1
  1846. " Line is not in proper tags format or Tag type is not supported
  1847. return
  1848. endif
  1849. " Update the total tag count
  1850. let s:tidx = s:tidx + 1
  1851. " The following variables are used to optimize this code. Vim is slow in
  1852. " using curly brace names. To reduce the amount of processing needed, the
  1853. " curly brace variables are pre-processed here
  1854. let fidx_tidx = 's:tlist_' . s:fidx . '_' . s:tidx
  1855. let fidx_ttype = 's:tlist_' . s:fidx . '_' . ttype
  1856. " Update the count of this tag type
  1857. let ttype_idx = {fidx_ttype}_count + 1
  1858. let {fidx_ttype}_count = ttype_idx
  1859. " Store the ctags output for this tag
  1860. let {fidx_tidx}_tag = a:tag_line
  1861. " Store the tag index and the tag type index (back pointers)
  1862. let {fidx_ttype}_{ttype_idx} = s:tidx
  1863. let {fidx_tidx}_ttype_idx = ttype_idx
  1864. " Extract the tag name
  1865. let tag_name = strpart(a:tag_line, 0, stridx(a:tag_line, "\t"))
  1866. " Extract the tag scope/prototype
  1867. if g:Tlist_Display_Prototype
  1868. let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(s:fidx, s:tidx)
  1869. else
  1870. let ttxt = ' ' . tag_name
  1871. " Add the tag scope, if it is available and is configured. Tag
  1872. " scope is the last field after the 'line:<num>\t' field
  1873. if g:Tlist_Display_Tag_Scope
  1874. let tag_scope = s:Tlist_Extract_Tag_Scope(a:tag_line)
  1875. if tag_scope != ''
  1876. let ttxt = ttxt . ' [' . tag_scope . ']'
  1877. endif
  1878. endif
  1879. endif
  1880. " Add this tag to the tag type variable
  1881. let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
  1882. " Save the tag name
  1883. let {fidx_tidx}_tag_name = tag_name
  1884. endfunction
  1885. " Tlist_Process_File
  1886. " Get the list of tags defined in the specified file and store them
  1887. " in Vim variables. Returns the file index where the tags are stored.
  1888. function! s:Tlist_Process_File(filename, ftype)
  1889. call s:Tlist_Log_Msg('Tlist_Process_File (' . a:filename . ', ' .
  1890. \ a:ftype . ')')
  1891. " Check whether this file is supported
  1892. if s:Tlist_Skip_File(a:filename, a:ftype)
  1893. return -1
  1894. endif
  1895. " If the tag types for this filetype are not yet created, then create
  1896. " them now
  1897. let var = 's:tlist_' . a:ftype . '_count'
  1898. if !exists(var)
  1899. if s:Tlist_FileType_Init(a:ftype) == 0
  1900. return -1
  1901. endif
  1902. endif
  1903. " If this file is already processed, then use the cached values
  1904. let fidx = s:Tlist_Get_File_Index(a:filename)
  1905. if fidx == -1
  1906. " First time, this file is loaded
  1907. let fidx = s:Tlist_Init_File(a:filename, a:ftype)
  1908. else
  1909. " File was previously processed. Discard the tag information
  1910. call s:Tlist_Discard_TagInfo(fidx)
  1911. endif
  1912. let s:tlist_{fidx}_valid = 1
  1913. " Exuberant ctags arguments to generate a tag list
  1914. let ctags_args = ' -f - --format=2 --excmd=pattern --fields=nks '
  1915. " Form the ctags argument depending on the sort type
  1916. if s:tlist_{fidx}_sort_type == 'name'
  1917. let ctags_args = ctags_args . '--sort=yes'
  1918. else
  1919. let ctags_args = ctags_args . '--sort=no'
  1920. endif
  1921. " Add the filetype specific arguments
  1922. let ctags_args = ctags_args . ' ' . s:tlist_{a:ftype}_ctags_args
  1923. " Ctags command to produce output with regexp for locating the tags
  1924. let ctags_cmd = g:Tlist_Ctags_Cmd . ctags_args
  1925. let ctags_cmd = ctags_cmd . ' "' . a:filename . '"'
  1926. if &shellxquote == '"'
  1927. " Double-quotes within double-quotes will not work in the
  1928. " command-line.If the 'shellxquote' option is set to double-quotes,
  1929. " then escape the double-quotes in the ctags command-line.
  1930. let ctags_cmd = escape(ctags_cmd, '"')
  1931. endif
  1932. " In Windows 95, if not using cygwin, disable the 'shellslash'
  1933. " option. Otherwise, this will cause problems when running the
  1934. " ctags command.
  1935. if has('win95') && !has('win32unix')
  1936. let old_shellslash = &shellslash
  1937. set noshellslash
  1938. endif
  1939. if has('win32') && !has('win32unix') && !has('win95')
  1940. \ && (&shell =~ 'cmd.exe')
  1941. " Windows does not correctly deal with commands that have more than 1
  1942. " set of double quotes. It will strip them all resulting in:
  1943. " 'C:\Program' is not recognized as an internal or external command
  1944. " operable program or batch file. To work around this, place the
  1945. " command inside a batch file and call the batch file.
  1946. " Do this only on Win2K, WinXP and above.
  1947. " Contributed by: David Fishburn.
  1948. let s:taglist_tempfile = fnamemodify(tempname(), ':h') .
  1949. \ '\taglist.cmd'
  1950. exe 'redir! > ' . s:taglist_tempfile
  1951. silent echo ctags_cmd
  1952. redir END
  1953. call s:Tlist_Log_Msg('Cmd inside batch file: ' . ctags_cmd)
  1954. let ctags_cmd = '"' . s:taglist_tempfile . '"'
  1955. endif
  1956. call s:Tlist_Log_Msg('Cmd: ' . ctags_cmd)
  1957. " Run ctags and get the tag list
  1958. let cmd_output = system(ctags_cmd)
  1959. " Restore the value of the 'shellslash' option.
  1960. if has('win95') && !has('win32unix')
  1961. let &shellslash = old_shellslash
  1962. endif
  1963. if exists('s:taglist_tempfile')
  1964. " Delete the temporary cmd file created on MS-Windows
  1965. call delete(s:taglist_tempfile)
  1966. endif
  1967. " Handle errors
  1968. if v:shell_error
  1969. let msg = "Taglist: Failed to generate tags for " . a:filename
  1970. call s:Tlist_Warning_Msg(msg)
  1971. if cmd_output != ''
  1972. call s:Tlist_Warning_Msg(cmd_output)
  1973. endif
  1974. return fidx
  1975. endif
  1976. " Store the modification time for the file
  1977. let s:tlist_{fidx}_mtime = getftime(a:filename)
  1978. " No tags for current file
  1979. if cmd_output == ''
  1980. call s:Tlist_Log_Msg('No tags defined in ' . a:filename)
  1981. return fidx
  1982. endif
  1983. call s:Tlist_Log_Msg('Generated tags information for ' . a:filename)
  1984. if v:version > 601
  1985. " The following script local variables are used by the
  1986. " Tlist_Parse_Tagline() function.
  1987. let s:ctags_flags = s:tlist_{a:ftype}_ctags_flags
  1988. let s:fidx = fidx
  1989. let s:tidx = 0
  1990. " Process the ctags output one line at a time. The substitute()
  1991. " command is used to parse the tag lines instead of using the
  1992. " matchstr()/stridx()/strpart() functions for performance reason
  1993. call substitute(cmd_output, "\\([^\n]\\+\\)\n",
  1994. \ '\=s:Tlist_Parse_Tagline(submatch(1))', 'g')
  1995. " Save the number of tags for this file
  1996. let s:tlist_{fidx}_tag_count = s:tidx
  1997. " The following script local variables are no longer needed
  1998. unlet! s:ctags_flags
  1999. unlet! s:tidx
  2000. unlet! s:fidx
  2001. else
  2002. " Due to a bug in Vim earlier than version 6.1,
  2003. " we cannot use substitute() to parse the ctags output.
  2004. " Instead the slow str*() functions are used
  2005. let ctags_flags = s:tlist_{a:ftype}_ctags_flags
  2006. let tidx = 0
  2007. while cmd_output != ''
  2008. " Extract one line at a time
  2009. let idx = stridx(cmd_output, "\n")
  2010. let one_line = strpart(cmd_output, 0, idx)
  2011. " Remove the line from the tags output
  2012. let cmd_output = strpart(cmd_output, idx + 1)
  2013. if one_line == ''
  2014. " Line is not in proper tags format
  2015. continue
  2016. endif
  2017. " Extract the tag type
  2018. let ttype = s:Tlist_Extract_Tagtype(one_line)
  2019. " Make sure the tag type is a valid and supported one
  2020. if ttype == '' || stridx(ctags_flags, ttype) == -1
  2021. " Line is not in proper tags format or Tag type is not
  2022. " supported
  2023. continue
  2024. endif
  2025. " Update the total tag count
  2026. let tidx = tidx + 1
  2027. " The following variables are used to optimize this code. Vim is
  2028. " slow in using curly brace names. To reduce the amount of
  2029. " processing needed, the curly brace variables are pre-processed
  2030. " here
  2031. let fidx_tidx = 's:tlist_' . fidx . '_' . tidx
  2032. let fidx_ttype = 's:tlist_' . fidx . '_' . ttype
  2033. " Update the count of this tag type
  2034. let ttype_idx = {fidx_ttype}_count + 1
  2035. let {fidx_ttype}_count = ttype_idx
  2036. " Store the ctags output for this tag
  2037. let {fidx_tidx}_tag = one_line
  2038. " Store the tag index and the tag type index (back pointers)
  2039. let {fidx_ttype}_{ttype_idx} = tidx
  2040. let {fidx_tidx}_ttype_idx = ttype_idx
  2041. " Extract the tag name
  2042. let tag_name = strpart(one_line, 0, stridx(one_line, "\t"))
  2043. " Extract the tag scope/prototype
  2044. if g:Tlist_Display_Prototype
  2045. let ttxt = ' ' . s:Tlist_Get_Tag_Prototype(fidx, tidx)
  2046. else
  2047. let ttxt = ' ' . tag_name
  2048. " Add the tag scope, if it is available and is configured. Tag
  2049. " scope is the last field after the 'line:<num>\t' field
  2050. if g:Tlist_Display_Tag_Scope
  2051. let tag_scope = s:Tlist_Extract_Tag_Scope(one_line)
  2052. if tag_scope != ''
  2053. let ttxt = ttxt . ' [' . tag_scope . ']'
  2054. endif
  2055. endif
  2056. endif
  2057. " Add this tag to the tag type variable
  2058. let {fidx_ttype} = {fidx_ttype} . ttxt . "\n"
  2059. " Save the tag name
  2060. let {fidx_tidx}_tag_name = tag_name
  2061. endwhile
  2062. " Save the number of tags for this file
  2063. let s:tlist_{fidx}_tag_count = tidx
  2064. endif
  2065. call s:Tlist_Log_Msg('Processed ' . s:tlist_{fidx}_tag_count .
  2066. \ ' tags in ' . a:filename)
  2067. return fidx
  2068. endfunction
  2069. " Tlist_Update_File
  2070. " Update the tags for a file (if needed)
  2071. function! Tlist_Update_File(filename, ftype)
  2072. call s:Tlist_Log_Msg('Tlist_Update_File (' . a:filename . ')')
  2073. " If the file doesn't support tag listing, skip it
  2074. if s:Tlist_Skip_File(a:filename, a:ftype)
  2075. return
  2076. endif
  2077. " Convert the file name to a full path
  2078. let fname = fnamemodify(a:filename, ':p')
  2079. " First check whether the file already exists
  2080. let fidx = s:Tlist_Get_File_Index(fname)
  2081. if fidx != -1 && s:tlist_{fidx}_valid
  2082. " File exists and the tags are valid
  2083. " Check whether the file was modified after the last tags update
  2084. " If it is modified, then update the tags
  2085. if s:tlist_{fidx}_mtime == getftime(fname)
  2086. return
  2087. endif
  2088. else
  2089. " If the tags were removed previously based on a user request,
  2090. " as we are going to update the tags (based on the user request),
  2091. " remove the filename from the deleted list
  2092. call s:Tlist_Update_Remove_List(fname, 0)
  2093. endif
  2094. " If the taglist window is opened, update it
  2095. let winnum = bufwinnr(g:TagList_title)
  2096. if winnum == -1
  2097. " Taglist window is not present. Just update the taglist
  2098. " and return
  2099. call s:Tlist_Process_File(fname, a:ftype)
  2100. else
  2101. if g:Tlist_Show_One_File && s:tlist_cur_file_idx != -1
  2102. " If tags for only one file are displayed and we are not
  2103. " updating the tags for that file, then no need to
  2104. " refresh the taglist window. Otherwise, the taglist
  2105. " window should be updated.
  2106. if s:tlist_{s:tlist_cur_file_idx}_filename != fname
  2107. call s:Tlist_Process_File(fname, a:ftype)
  2108. return
  2109. endif
  2110. endif
  2111. " Save the current window number
  2112. let save_winnr = winnr()
  2113. " Goto the taglist window
  2114. call s:Tlist_Window_Goto_Window()
  2115. " Save the cursor position
  2116. let save_line = line('.')
  2117. let save_col = col('.')
  2118. " Update the taglist window
  2119. call s:Tlist_Window_Refresh_File(fname, a:ftype)
  2120. " Restore the cursor position
  2121. if v:version >= 601
  2122. call cursor(save_line, save_col)
  2123. else
  2124. exe save_line
  2125. exe 'normal! ' . save_col . '|'
  2126. endif
  2127. if winnr() != save_winnr
  2128. " Go back to the original window
  2129. call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
  2130. endif
  2131. endif
  2132. " Update the taglist menu
  2133. if g:Tlist_Show_Menu
  2134. call s:Tlist_Menu_Update_File(1)
  2135. endif
  2136. endfunction
  2137. " Tlist_Window_Close
  2138. " Close the taglist window
  2139. function! s:Tlist_Window_Close()
  2140. call s:Tlist_Log_Msg('Tlist_Window_Close()')
  2141. " Make sure the taglist window exists
  2142. let winnum = bufwinnr(g:TagList_title)
  2143. if winnum == -1
  2144. call s:Tlist_Warning_Msg('Error: Taglist window is not open')
  2145. return
  2146. endif
  2147. if winnr() == winnum
  2148. " Already in the taglist window. Close it and return
  2149. if winbufnr(2) != -1
  2150. " If a window other than the taglist window is open,
  2151. " then only close the taglist window.
  2152. close
  2153. endif
  2154. else
  2155. " Goto the taglist window, close it and then come back to the
  2156. " original window
  2157. let curbufnr = bufnr('%')
  2158. exe winnum . 'wincmd w'
  2159. close
  2160. " Need to jump back to the original window only if we are not
  2161. " already in that window
  2162. let winnum = bufwinnr(curbufnr)
  2163. if winnr() != winnum
  2164. exe winnum . 'wincmd w'
  2165. endif
  2166. endif
  2167. endfunction
  2168. " Tlist_Window_Mark_File_Window
  2169. " Mark the current window as the file window to use when jumping to a tag.
  2170. " Only if the current window is a non-plugin, non-preview and non-taglist
  2171. " window
  2172. function! s:Tlist_Window_Mark_File_Window()
  2173. if getbufvar('%', '&buftype') == '' && !&previewwindow
  2174. let w:tlist_file_window = "yes"
  2175. endif
  2176. endfunction
  2177. " Tlist_Window_Open
  2178. " Open and refresh the taglist window
  2179. function! s:Tlist_Window_Open()
  2180. call s:Tlist_Log_Msg('Tlist_Window_Open()')
  2181. " If the window is open, jump to it
  2182. let winnum = bufwinnr(g:TagList_title)
  2183. if winnum != -1
  2184. " Jump to the existing window
  2185. if winnr() != winnum
  2186. exe winnum . 'wincmd w'
  2187. endif
  2188. return
  2189. endif
  2190. if s:tlist_app_name == "winmanager"
  2191. " Taglist plugin is no longer part of the winmanager app
  2192. let s:tlist_app_name = "none"
  2193. endif
  2194. " Get the filename and filetype for the specified buffer
  2195. let curbuf_name = fnamemodify(bufname('%'), ':p')
  2196. let curbuf_ftype = s:Tlist_Get_Buffer_Filetype('%')
  2197. let cur_lnum = line('.')
  2198. " Mark the current window as the desired window to open a file when a tag
  2199. " is selected.
  2200. call s:Tlist_Window_Mark_File_Window()
  2201. " Open the taglist window
  2202. call s:Tlist_Window_Create()
  2203. call s:Tlist_Window_Refresh()
  2204. if g:Tlist_Show_One_File
  2205. " Add only the current buffer and file
  2206. "
  2207. " If the file doesn't support tag listing, skip it
  2208. if !s:Tlist_Skip_File(curbuf_name, curbuf_ftype)
  2209. call s:Tlist_Window_Refresh_File(curbuf_name, curbuf_ftype)
  2210. endif
  2211. endif
  2212. if g:Tlist_File_Fold_Auto_Close
  2213. " Open the fold for the current file, as all the folds in
  2214. " the taglist window are closed
  2215. let fidx = s:Tlist_Get_File_Index(curbuf_name)
  2216. if fidx != -1
  2217. exe "silent! " . s:tlist_{fidx}_start . "," .
  2218. \ s:tlist_{fidx}_end . "foldopen!"
  2219. endif
  2220. endif
  2221. " Highlight the current tag
  2222. call s:Tlist_Window_Highlight_Tag(curbuf_name, cur_lnum, 1, 1)
  2223. endfunction
  2224. " Tlist_Window_Toggle()
  2225. " Open or close a taglist window
  2226. function! s:Tlist_Window_Toggle()
  2227. call s:Tlist_Log_Msg('Tlist_Window_Toggle()')
  2228. " If taglist window is open then close it.
  2229. let winnum = bufwinnr(g:TagList_title)
  2230. if winnum != -1
  2231. call s:Tlist_Window_Close()
  2232. return
  2233. endif
  2234. call s:Tlist_Window_Open()
  2235. " Go back to the original window, if Tlist_GainFocus_On_ToggleOpen is not
  2236. " set
  2237. if !g:Tlist_GainFocus_On_ToggleOpen
  2238. call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
  2239. endif
  2240. " Update the taglist menu
  2241. if g:Tlist_Show_Menu
  2242. call s:Tlist_Menu_Update_File(0)
  2243. endif
  2244. endfunction
  2245. " Tlist_Process_Filelist
  2246. " Process multiple files. Each filename is separated by "\n"
  2247. " Returns the number of processed files
  2248. function! s:Tlist_Process_Filelist(file_names)
  2249. let flist = a:file_names
  2250. " Enable lazy screen updates
  2251. let old_lazyredraw = &lazyredraw
  2252. set lazyredraw
  2253. " Keep track of the number of processed files
  2254. let fcnt = 0
  2255. " Process one file at a time
  2256. while flist != ''
  2257. let nl_idx = stridx(flist, "\n")
  2258. let one_file = strpart(flist, 0, nl_idx)
  2259. " Remove the filename from the list
  2260. let flist = strpart(flist, nl_idx + 1)
  2261. if one_file == ''
  2262. continue
  2263. endif
  2264. " Skip directories
  2265. if isdirectory(one_file)
  2266. continue
  2267. endif
  2268. let ftype = s:Tlist_Detect_Filetype(one_file)
  2269. echon "\r "
  2270. echon "\rProcessing tags for " . fnamemodify(one_file, ':p:t')
  2271. let fcnt = fcnt + 1
  2272. call Tlist_Update_File(one_file, ftype)
  2273. endwhile
  2274. " Clear the displayed informational messages
  2275. echon "\r "
  2276. " Restore the previous state
  2277. let &lazyredraw = old_lazyredraw
  2278. return fcnt
  2279. endfunction
  2280. " Tlist_Process_Dir
  2281. " Process the files in a directory matching the specified pattern
  2282. function! s:Tlist_Process_Dir(dir_name, pat)
  2283. let flist = glob(a:dir_name . '/' . a:pat) . "\n"
  2284. let fcnt = s:Tlist_Process_Filelist(flist)
  2285. let len = strlen(a:dir_name)
  2286. if a:dir_name[len - 1] == '\' || a:dir_name[len - 1] == '/'
  2287. let glob_expr = a:dir_name . '*'
  2288. else
  2289. let glob_expr = a:dir_name . '/*'
  2290. endif
  2291. let all_files = glob(glob_expr) . "\n"
  2292. while all_files != ''
  2293. let nl_idx = stridx(all_files, "\n")
  2294. let one_file = strpart(all_files, 0, nl_idx)
  2295. let all_files = strpart(all_files, nl_idx + 1)
  2296. if one_file == ''
  2297. continue
  2298. endif
  2299. " Skip non-directory names
  2300. if !isdirectory(one_file)
  2301. continue
  2302. endif
  2303. echon "\r "
  2304. echon "\rProcessing files in directory " . fnamemodify(one_file, ':t')
  2305. let fcnt = fcnt + s:Tlist_Process_Dir(one_file, a:pat)
  2306. endwhile
  2307. return fcnt
  2308. endfunction
  2309. " Tlist_Add_Files_Recursive
  2310. " Add files recursively from a directory
  2311. function! s:Tlist_Add_Files_Recursive(dir, ...)
  2312. let dir_name = fnamemodify(a:dir, ':p')
  2313. if !isdirectory(dir_name)
  2314. call s:Tlist_Warning_Msg('Error: ' . dir_name . ' is not a directory')
  2315. return
  2316. endif
  2317. if a:0 == 1
  2318. " User specified file pattern
  2319. let pat = a:1
  2320. else
  2321. " Default file pattern
  2322. let pat = '*'
  2323. endif
  2324. echon "\r "
  2325. echon "\rProcessing files in directory " . fnamemodify(dir_name, ':t')
  2326. let fcnt = s:Tlist_Process_Dir(dir_name, pat)
  2327. echon "\rAdded " . fcnt . " files to the taglist"
  2328. endfunction
  2329. " Tlist_Add_Files
  2330. " Add the specified list of files to the taglist
  2331. function! s:Tlist_Add_Files(...)
  2332. let flist = ''
  2333. let i = 1
  2334. " Get all the files matching the file patterns supplied as argument
  2335. while i <= a:0
  2336. let flist = flist . glob(a:{i}) . "\n"
  2337. let i = i + 1
  2338. endwhile
  2339. if flist == ''
  2340. call s:Tlist_Warning_Msg('Error: No matching files are found')
  2341. return
  2342. endif
  2343. let fcnt = s:Tlist_Process_Filelist(flist)
  2344. echon "\rAdded " . fcnt . " files to the taglist"
  2345. endfunction
  2346. " Tlist_Extract_Tagtype
  2347. " Extract the tag type from the tag text
  2348. function! s:Tlist_Extract_Tagtype(tag_line)
  2349. " The tag type is after the tag prototype field. The prototype field
  2350. " ends with the /;"\t string. We add 4 at the end to skip the characters
  2351. " in this special string..
  2352. let start = strridx(a:tag_line, '/;"' . "\t") + 4
  2353. let end = strridx(a:tag_line, 'line:') - 1
  2354. let ttype = strpart(a:tag_line, start, end - start)
  2355. return ttype
  2356. endfunction
  2357. " Tlist_Extract_Tag_Scope
  2358. " Extract the tag scope from the tag text
  2359. function! s:Tlist_Extract_Tag_Scope(tag_line)
  2360. let start = strridx(a:tag_line, 'line:')
  2361. let end = strridx(a:tag_line, "\t")
  2362. if end <= start
  2363. return ''
  2364. endif
  2365. let tag_scope = strpart(a:tag_line, end + 1)
  2366. let tag_scope = strpart(tag_scope, stridx(tag_scope, ':') + 1)
  2367. return tag_scope
  2368. endfunction
  2369. " Tlist_Refresh()
  2370. " Refresh the taglist
  2371. function! s:Tlist_Refresh()
  2372. call s:Tlist_Log_Msg('Tlist_Refresh (Skip_Refresh = ' .
  2373. \ s:Tlist_Skip_Refresh . ', ' . bufname('%') . ')')
  2374. " If we are entering the buffer from one of the taglist functions, then
  2375. " no need to refresh the taglist window again.
  2376. if s:Tlist_Skip_Refresh
  2377. " We still need to update the taglist menu
  2378. if g:Tlist_Show_Menu
  2379. call s:Tlist_Menu_Update_File(0)
  2380. endif
  2381. return
  2382. endif
  2383. " If part of the winmanager plugin and not configured to process
  2384. " tags always and not configured to display the tags menu, then return
  2385. if (s:tlist_app_name == 'winmanager') && !g:Tlist_Process_File_Always
  2386. \ && !g:Tlist_Show_Menu
  2387. return
  2388. endif
  2389. " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
  2390. if &buftype != ''
  2391. return
  2392. endif
  2393. let filename = fnamemodify(bufname('%'), ':p')
  2394. let ftype = s:Tlist_Get_Buffer_Filetype('%')
  2395. " If the file doesn't support tag listing, skip it
  2396. if s:Tlist_Skip_File(filename, ftype)
  2397. return
  2398. endif
  2399. let tlist_win = bufwinnr(g:TagList_title)
  2400. " If the taglist window is not opened and not configured to process
  2401. " tags always and not displaying the tags menu, then return
  2402. if tlist_win == -1 && !g:Tlist_Process_File_Always && !g:Tlist_Show_Menu
  2403. return
  2404. endif
  2405. let fidx = s:Tlist_Get_File_Index(filename)
  2406. if fidx == -1
  2407. " Check whether this file is removed based on user request
  2408. " If it is, then don't display the tags for this file
  2409. if s:Tlist_User_Removed_File(filename)
  2410. return
  2411. endif
  2412. " If the taglist should not be auto updated, then return
  2413. if !g:Tlist_Auto_Update
  2414. return
  2415. endif
  2416. endif
  2417. let cur_lnum = line('.')
  2418. if fidx == -1
  2419. " Update the tags for the file
  2420. let fidx = s:Tlist_Process_File(filename, ftype)
  2421. else
  2422. let mtime = getftime(filename)
  2423. if s:tlist_{fidx}_mtime != mtime
  2424. " Invalidate the tags listed for this file
  2425. let s:tlist_{fidx}_valid = 0
  2426. " Update the taglist and the window
  2427. call Tlist_Update_File(filename, ftype)
  2428. " Store the new file modification time
  2429. let s:tlist_{fidx}_mtime = mtime
  2430. endif
  2431. endif
  2432. " Update the taglist window
  2433. if tlist_win != -1
  2434. " Disable screen updates
  2435. let old_lazyredraw = &lazyredraw
  2436. set nolazyredraw
  2437. " Save the current window number
  2438. let save_winnr = winnr()
  2439. " Goto the taglist window
  2440. call s:Tlist_Window_Goto_Window()
  2441. if !g:Tlist_Auto_Highlight_Tag || !g:Tlist_Highlight_Tag_On_BufEnter
  2442. " Save the cursor position
  2443. let save_line = line('.')
  2444. let save_col = col('.')
  2445. endif
  2446. " Update the taglist window
  2447. call s:Tlist_Window_Refresh_File(filename, ftype)
  2448. " Open the fold for the file
  2449. exe "silent! " . s:tlist_{fidx}_start . "," .
  2450. \ s:tlist_{fidx}_end . "foldopen!"
  2451. if g:Tlist_Highlight_Tag_On_BufEnter && g:Tlist_Auto_Highlight_Tag
  2452. if g:Tlist_Show_One_File && s:tlist_cur_file_idx != fidx
  2453. " If displaying tags for only one file in the taglist
  2454. " window and about to display the tags for a new file,
  2455. " then center the current tag line for the new file
  2456. let center_tag_line = 1
  2457. else
  2458. let center_tag_line = 0
  2459. endif
  2460. " Highlight the current tag
  2461. call s:Tlist_Window_Highlight_Tag(filename, cur_lnum, 1, center_tag_line)
  2462. else
  2463. " Restore the cursor position
  2464. if v:version >= 601
  2465. call cursor(save_line, save_col)
  2466. else
  2467. exe save_line
  2468. exe 'normal! ' . save_col . '|'
  2469. endif
  2470. endif
  2471. " Jump back to the original window
  2472. if save_winnr != winnr()
  2473. call s:Tlist_Exe_Cmd_No_Acmds(save_winnr . 'wincmd w')
  2474. endif
  2475. " Restore screen updates
  2476. let &lazyredraw = old_lazyredraw
  2477. endif
  2478. " Update the taglist menu
  2479. if g:Tlist_Show_Menu
  2480. call s:Tlist_Menu_Update_File(0)
  2481. endif
  2482. endfunction
  2483. " Tlist_Change_Sort()
  2484. " Change the sort order of the tag listing
  2485. " caller == 'cmd', command used in the taglist window
  2486. " caller == 'menu', taglist menu
  2487. " action == 'toggle', toggle sort from name to order and vice versa
  2488. " action == 'set', set the sort order to sort_type
  2489. function! s:Tlist_Change_Sort(caller, action, sort_type)
  2490. call s:Tlist_Log_Msg('Tlist_Change_Sort (caller = ' . a:caller .
  2491. \ ', action = ' . a:action . ', sort_type = ' . a:sort_type . ')')
  2492. if a:caller == 'cmd'
  2493. let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
  2494. if fidx == -1
  2495. return
  2496. endif
  2497. " Remove the previous highlighting
  2498. match none
  2499. elseif a:caller == 'menu'
  2500. let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
  2501. if fidx == -1
  2502. return
  2503. endif
  2504. endif
  2505. if a:action == 'toggle'
  2506. let sort_type = s:tlist_{fidx}_sort_type
  2507. " Toggle the sort order from 'name' to 'order' and vice versa
  2508. if sort_type == 'name'
  2509. let s:tlist_{fidx}_sort_type = 'order'
  2510. else
  2511. let s:tlist_{fidx}_sort_type = 'name'
  2512. endif
  2513. else
  2514. let s:tlist_{fidx}_sort_type = a:sort_type
  2515. endif
  2516. " Invalidate the tags listed for this file
  2517. let s:tlist_{fidx}_valid = 0
  2518. if a:caller == 'cmd'
  2519. " Save the current line for later restoration
  2520. let curline = '\V\^' . getline('.') . '\$'
  2521. call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
  2522. \ s:tlist_{fidx}_filetype)
  2523. exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
  2524. " Go back to the cursor line before the tag list is sorted
  2525. call search(curline, 'w')
  2526. call s:Tlist_Menu_Update_File(1)
  2527. else
  2528. call s:Tlist_Menu_Remove_File()
  2529. call s:Tlist_Refresh()
  2530. endif
  2531. endfunction
  2532. " Tlist_Update_Current_File()
  2533. " Update taglist for the current buffer by regenerating the tag list
  2534. " Contributed by WEN Guopeng.
  2535. function! s:Tlist_Update_Current_File()
  2536. call s:Tlist_Log_Msg('Tlist_Update_Current_File()')
  2537. if winnr() == bufwinnr(g:TagList_title)
  2538. " In the taglist window. Update the current file
  2539. call s:Tlist_Window_Update_File()
  2540. else
  2541. " Not in the taglist window. Update the current buffer
  2542. let filename = fnamemodify(bufname('%'), ':p')
  2543. let fidx = s:Tlist_Get_File_Index(filename)
  2544. if fidx != -1
  2545. let s:tlist_{fidx}_valid = 0
  2546. endif
  2547. let ft = s:Tlist_Get_Buffer_Filetype('%')
  2548. call Tlist_Update_File(filename, ft)
  2549. endif
  2550. endfunction
  2551. " Tlist_Window_Update_File()
  2552. " Update the tags displayed in the taglist window
  2553. function! s:Tlist_Window_Update_File()
  2554. call s:Tlist_Log_Msg('Tlist_Window_Update_File()')
  2555. let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
  2556. if fidx == -1
  2557. return
  2558. endif
  2559. " Remove the previous highlighting
  2560. match none
  2561. " Save the current line for later restoration
  2562. let curline = '\V\^' . getline('.') . '\$'
  2563. let s:tlist_{fidx}_valid = 0
  2564. " Update the taglist window
  2565. call s:Tlist_Window_Refresh_File(s:tlist_{fidx}_filename,
  2566. \ s:tlist_{fidx}_filetype)
  2567. exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'foldopen!'
  2568. " Go back to the tag line before the list is updated
  2569. call search(curline, 'w')
  2570. endfunction
  2571. " Tlist_Window_Get_Tag_Type_By_Linenum()
  2572. " Return the tag type index for the specified line in the taglist window
  2573. function! s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
  2574. let ftype = s:tlist_{a:fidx}_filetype
  2575. " Determine to which tag type the current line number belongs to using the
  2576. " tag type start line number and the number of tags in a tag type
  2577. let i = 1
  2578. while i <= s:tlist_{ftype}_count
  2579. let ttype = s:tlist_{ftype}_{i}_name
  2580. let start_lnum =
  2581. \ s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
  2582. let end = start_lnum + s:tlist_{a:fidx}_{ttype}_count
  2583. if a:lnum >= start_lnum && a:lnum <= end
  2584. break
  2585. endif
  2586. let i = i + 1
  2587. endwhile
  2588. " Current line doesn't belong to any of the displayed tag types
  2589. if i > s:tlist_{ftype}_count
  2590. return ''
  2591. endif
  2592. return ttype
  2593. endfunction
  2594. " Tlist_Window_Get_Tag_Index()
  2595. " Return the tag index for the specified line in the taglist window
  2596. function! s:Tlist_Window_Get_Tag_Index(fidx, lnum)
  2597. let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(a:fidx, a:lnum)
  2598. " Current line doesn't belong to any of the displayed tag types
  2599. if ttype == ''
  2600. return 0
  2601. endif
  2602. " Compute the index into the displayed tags for the tag type
  2603. let ttype_lnum = s:tlist_{a:fidx}_start + s:tlist_{a:fidx}_{ttype}_offset
  2604. let tidx = a:lnum - ttype_lnum
  2605. if tidx == 0
  2606. return 0
  2607. endif
  2608. " Get the corresponding tag line and return it
  2609. return s:tlist_{a:fidx}_{ttype}_{tidx}
  2610. endfunction
  2611. " Tlist_Window_Highlight_Line
  2612. " Highlight the current line
  2613. function! s:Tlist_Window_Highlight_Line()
  2614. " Clear previously selected name
  2615. match none
  2616. " Highlight the current line
  2617. if g:Tlist_Display_Prototype == 0
  2618. let pat = '/\%' . line('.') . 'l\s\+\zs.*/'
  2619. else
  2620. let pat = '/\%' . line('.') . 'l.*/'
  2621. endif
  2622. exe 'match TagListTagName ' . pat
  2623. endfunction
  2624. " Tlist_Window_Open_File
  2625. " Open the specified file in either a new window or an existing window
  2626. " and place the cursor at the specified tag pattern
  2627. function! s:Tlist_Window_Open_File(win_ctrl, filename, tagpat)
  2628. call s:Tlist_Log_Msg('Tlist_Window_Open_File (' . a:filename . ',' .
  2629. \ a:win_ctrl . ')')
  2630. let prev_Tlist_Skip_Refresh = s:Tlist_Skip_Refresh
  2631. let s:Tlist_Skip_Refresh = 1
  2632. if s:tlist_app_name == "winmanager"
  2633. " Let the winmanager edit the file
  2634. call WinManagerFileEdit(a:filename, a:win_ctrl == 'newwin')
  2635. else
  2636. if a:win_ctrl == 'newtab'
  2637. " Create a new tab
  2638. exe 'tabnew ' . escape(a:filename, ' ')
  2639. " Open the taglist window in the new tab
  2640. call s:Tlist_Window_Open()
  2641. endif
  2642. if a:win_ctrl == 'checktab'
  2643. " Check whether the file is present in any of the tabs.
  2644. " If the file is present in the current tab, then use the
  2645. " current tab.
  2646. if bufwinnr(a:filename) != -1
  2647. let file_present_in_tab = 1
  2648. let i = tabpagenr()
  2649. else
  2650. let i = 1
  2651. let bnum = bufnr(a:filename)
  2652. let file_present_in_tab = 0
  2653. while i <= tabpagenr('$')
  2654. if index(tabpagebuflist(i), bnum) != -1
  2655. let file_present_in_tab = 1
  2656. break
  2657. endif
  2658. let i += 1
  2659. endwhile
  2660. endif
  2661. if file_present_in_tab
  2662. " Goto the tab containing the file
  2663. exe 'tabnext ' . i
  2664. else
  2665. " Open a new tab
  2666. exe 'tabnew ' . escape(a:filename, ' ')
  2667. " Open the taglist window
  2668. call s:Tlist_Window_Open()
  2669. endif
  2670. endif
  2671. let winnum = -1
  2672. if a:win_ctrl == 'prevwin'
  2673. " Open the file in the previous window, if it is usable
  2674. let cur_win = winnr()
  2675. wincmd p
  2676. if &buftype == '' && !&previewwindow
  2677. exe "edit " . escape(a:filename, ' ')
  2678. let winnum = winnr()
  2679. else
  2680. " Previous window is not usable
  2681. exe cur_win . 'wincmd w'
  2682. endif
  2683. endif
  2684. " Goto the window containing the file. If the window is not there, open a
  2685. " new window
  2686. if winnum == -1
  2687. let winnum = bufwinnr(a:filename)
  2688. endif
  2689. if winnum == -1
  2690. " Locate the previously used window for opening a file
  2691. let fwin_num = 0
  2692. let first_usable_win = 0
  2693. let i = 1
  2694. let bnum = winbufnr(i)
  2695. while bnum != -1
  2696. if getwinvar(i, 'tlist_file_window') == 'yes'
  2697. let fwin_num = i
  2698. break
  2699. endif
  2700. if first_usable_win == 0 &&
  2701. \ getbufvar(bnum, '&buftype') == '' &&
  2702. \ !getwinvar(i, '&previewwindow')
  2703. " First non-taglist, non-plugin and non-preview window
  2704. let first_usable_win = i
  2705. endif
  2706. let i = i + 1
  2707. let bnum = winbufnr(i)
  2708. endwhile
  2709. " If a previously used window is not found, then use the first
  2710. " non-taglist window
  2711. if fwin_num == 0
  2712. let fwin_num = first_usable_win
  2713. endif
  2714. if fwin_num != 0
  2715. " Jump to the file window
  2716. exe fwin_num . "wincmd w"
  2717. " If the user asked to jump to the tag in a new window, then split
  2718. " the existing window into two.
  2719. if a:win_ctrl == 'newwin'
  2720. split
  2721. endif
  2722. exe "edit " . escape(a:filename, ' ')
  2723. else
  2724. " Open a new window
  2725. if g:Tlist_Use_Horiz_Window
  2726. exe 'leftabove split ' . escape(a:filename, ' ')
  2727. else
  2728. if winbufnr(2) == -1
  2729. " Only the taglist window is present
  2730. if g:Tlist_Use_Right_Window
  2731. exe 'leftabove vertical split ' .
  2732. \ escape(a:filename, ' ')
  2733. else
  2734. exe 'rightbelow vertical split ' .
  2735. \ escape(a:filename, ' ')
  2736. endif
  2737. " Go to the taglist window to change the window size to
  2738. " the user configured value
  2739. call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
  2740. if g:Tlist_Use_Horiz_Window
  2741. exe 'resize ' . g:Tlist_WinHeight
  2742. else
  2743. exe 'vertical resize ' . g:Tlist_WinWidth
  2744. endif
  2745. " Go back to the file window
  2746. call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
  2747. else
  2748. " A plugin or help window is also present
  2749. wincmd w
  2750. exe 'leftabove split ' . escape(a:filename, ' ')
  2751. endif
  2752. endif
  2753. endif
  2754. " Mark the window, so that it can be reused.
  2755. call s:Tlist_Window_Mark_File_Window()
  2756. else
  2757. if v:version >= 700
  2758. " If the file is opened in more than one window, then check
  2759. " whether the last accessed window has the selected file.
  2760. " If it does, then use that window.
  2761. let lastwin_bufnum = winbufnr(winnr('#'))
  2762. if bufnr(a:filename) == lastwin_bufnum
  2763. let winnum = winnr('#')
  2764. endif
  2765. endif
  2766. exe winnum . 'wincmd w'
  2767. " If the user asked to jump to the tag in a new window, then split the
  2768. " existing window into two.
  2769. if a:win_ctrl == 'newwin'
  2770. split
  2771. endif
  2772. endif
  2773. endif
  2774. " Jump to the tag
  2775. if a:tagpat != ''
  2776. " Add the current cursor position to the jump list, so that user can
  2777. " jump back using the ' and ` marks.
  2778. mark '
  2779. silent call search(a:tagpat, 'w')
  2780. " Bring the line to the middle of the window
  2781. normal! z.
  2782. " If the line is inside a fold, open the fold
  2783. if foldclosed('.') != -1
  2784. .foldopen
  2785. endif
  2786. endif
  2787. " If the user selects to preview the tag then jump back to the
  2788. " taglist window
  2789. if a:win_ctrl == 'preview'
  2790. " Go back to the taglist window
  2791. let winnum = bufwinnr(g:TagList_title)
  2792. exe winnum . 'wincmd w'
  2793. else
  2794. " If the user has selected to close the taglist window, when a
  2795. " tag is selected, close the taglist window
  2796. if g:Tlist_Close_On_Select
  2797. call s:Tlist_Window_Goto_Window()
  2798. close
  2799. " Go back to the window displaying the selected file
  2800. let wnum = bufwinnr(a:filename)
  2801. if wnum != -1 && wnum != winnr()
  2802. call s:Tlist_Exe_Cmd_No_Acmds(wnum . 'wincmd w')
  2803. endif
  2804. endif
  2805. endif
  2806. let s:Tlist_Skip_Refresh = prev_Tlist_Skip_Refresh
  2807. endfunction
  2808. " Tlist_Window_Jump_To_Tag()
  2809. " Jump to the location of the current tag
  2810. " win_ctrl == useopen - Reuse the existing file window
  2811. " win_ctrl == newwin - Open a new window
  2812. " win_ctrl == preview - Preview the tag
  2813. " win_ctrl == prevwin - Open in previous window
  2814. " win_ctrl == newtab - Open in new tab
  2815. function! s:Tlist_Window_Jump_To_Tag(win_ctrl)
  2816. call s:Tlist_Log_Msg('Tlist_Window_Jump_To_Tag(' . a:win_ctrl . ')')
  2817. " Do not process comment lines and empty lines
  2818. let curline = getline('.')
  2819. if curline =~ '^\s*$' || curline[0] == '"'
  2820. return
  2821. endif
  2822. " If inside a closed fold, then use the first line of the fold
  2823. " and jump to the file.
  2824. let lnum = foldclosed('.')
  2825. if lnum == -1
  2826. " Jump to the selected tag or file
  2827. let lnum = line('.')
  2828. else
  2829. " Open the closed fold
  2830. .foldopen!
  2831. endif
  2832. let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
  2833. if fidx == -1
  2834. return
  2835. endif
  2836. " Get the tag output for the current tag
  2837. let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
  2838. if tidx != 0
  2839. let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, tidx)
  2840. " Highlight the tagline
  2841. call s:Tlist_Window_Highlight_Line()
  2842. else
  2843. " Selected a line which is not a tag name. Just edit the file
  2844. let tagpat = ''
  2845. endif
  2846. call s:Tlist_Window_Open_File(a:win_ctrl, s:tlist_{fidx}_filename, tagpat)
  2847. endfunction
  2848. " Tlist_Window_Show_Info()
  2849. " Display information about the entry under the cursor
  2850. function! s:Tlist_Window_Show_Info()
  2851. call s:Tlist_Log_Msg('Tlist_Window_Show_Info()')
  2852. " Clear the previously displayed line
  2853. echo
  2854. " Do not process comment lines and empty lines
  2855. let curline = getline('.')
  2856. if curline =~ '^\s*$' || curline[0] == '"'
  2857. return
  2858. endif
  2859. " If inside a fold, then don't display the prototype
  2860. if foldclosed('.') != -1
  2861. return
  2862. endif
  2863. let lnum = line('.')
  2864. " Get the file index
  2865. let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(lnum)
  2866. if fidx == -1
  2867. return
  2868. endif
  2869. if lnum == s:tlist_{fidx}_start
  2870. " Cursor is on a file name
  2871. let fname = s:tlist_{fidx}_filename
  2872. if strlen(fname) > 50
  2873. let fname = fnamemodify(fname, ':t')
  2874. endif
  2875. echo fname . ', Filetype=' . s:tlist_{fidx}_filetype .
  2876. \ ', Tag count=' . s:tlist_{fidx}_tag_count
  2877. return
  2878. endif
  2879. " Get the tag output line for the current tag
  2880. let tidx = s:Tlist_Window_Get_Tag_Index(fidx, lnum)
  2881. if tidx == 0
  2882. " Cursor is on a tag type
  2883. let ttype = s:Tlist_Window_Get_Tag_Type_By_Linenum(fidx, lnum)
  2884. if ttype == ''
  2885. return
  2886. endif
  2887. let ttype_name = ''
  2888. let ftype = s:tlist_{fidx}_filetype
  2889. let i = 1
  2890. while i <= s:tlist_{ftype}_count
  2891. if ttype == s:tlist_{ftype}_{i}_name
  2892. let ttype_name = s:tlist_{ftype}_{i}_fullname
  2893. break
  2894. endif
  2895. let i = i + 1
  2896. endwhile
  2897. echo 'Tag type=' . ttype_name .
  2898. \ ', Tag count=' . s:tlist_{fidx}_{ttype}_count
  2899. return
  2900. endif
  2901. " Get the tag search pattern and display it
  2902. echo s:Tlist_Get_Tag_Prototype(fidx, tidx)
  2903. endfunction
  2904. " Tlist_Find_Nearest_Tag_Idx
  2905. " Find the tag idx nearest to the supplied line number
  2906. " Returns -1, if a tag couldn't be found for the specified line number
  2907. function! s:Tlist_Find_Nearest_Tag_Idx(fidx, linenum)
  2908. let sort_type = s:tlist_{a:fidx}_sort_type
  2909. let left = 1
  2910. let right = s:tlist_{a:fidx}_tag_count
  2911. if sort_type == 'order'
  2912. " Tags sorted by order, use a binary search.
  2913. " The idea behind this function is taken from the ctags.vim script (by
  2914. " Alexey Marinichev) available at the Vim online website.
  2915. " If the current line is the less than the first tag, then no need to
  2916. " search
  2917. let first_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, 1)
  2918. if a:linenum < first_lnum
  2919. return -1
  2920. endif
  2921. while left < right
  2922. let middle = (right + left + 1) / 2
  2923. let middle_lnum = s:Tlist_Get_Tag_Linenum(a:fidx, middle)
  2924. if middle_lnum == a:linenum
  2925. let left = middle
  2926. break
  2927. endif
  2928. if middle_lnum > a:linenum
  2929. let right = middle - 1
  2930. else
  2931. let left = middle
  2932. endif
  2933. endwhile
  2934. else
  2935. " Tags sorted by name, use a linear search. (contributed by Dave
  2936. " Eggum).
  2937. " Look for a tag with a line number less than or equal to the supplied
  2938. " line number. If multiple tags are found, then use the tag with the
  2939. " line number closest to the supplied line number. IOW, use the tag
  2940. " with the highest line number.
  2941. let closest_lnum = 0
  2942. let final_left = 0
  2943. while left <= right
  2944. let lnum = s:Tlist_Get_Tag_Linenum(a:fidx, left)
  2945. if lnum < a:linenum && lnum > closest_lnum
  2946. let closest_lnum = lnum
  2947. let final_left = left
  2948. elseif lnum == a:linenum
  2949. let closest_lnum = lnum
  2950. let final_left = left
  2951. break
  2952. else
  2953. let left = left + 1
  2954. endif
  2955. endwhile
  2956. if closest_lnum == 0
  2957. return -1
  2958. endif
  2959. if left >= right
  2960. let left = final_left
  2961. endif
  2962. endif
  2963. return left
  2964. endfunction
  2965. " Tlist_Window_Highlight_Tag()
  2966. " Highlight the current tag
  2967. " cntx == 1, Called by the taglist plugin itself
  2968. " cntx == 2, Forced by the user through the TlistHighlightTag command
  2969. " center = 1, move the tag line to the center of the taglist window
  2970. function! s:Tlist_Window_Highlight_Tag(filename, cur_lnum, cntx, center)
  2971. " Highlight the current tag only if the user configured the
  2972. " taglist plugin to do so or if the user explictly invoked the
  2973. " command to highlight the current tag.
  2974. if !g:Tlist_Auto_Highlight_Tag && a:cntx == 1
  2975. return
  2976. endif
  2977. if a:filename == ''
  2978. return
  2979. endif
  2980. " Make sure the taglist window is present
  2981. let winnum = bufwinnr(g:TagList_title)
  2982. if winnum == -1
  2983. call s:Tlist_Warning_Msg('Error: Taglist window is not open')
  2984. return
  2985. endif
  2986. let fidx = s:Tlist_Get_File_Index(a:filename)
  2987. if fidx == -1
  2988. return
  2989. endif
  2990. " If the file is currently not displayed in the taglist window, then retrn
  2991. if !s:tlist_{fidx}_visible
  2992. return
  2993. endif
  2994. " If there are no tags for this file, then no need to proceed further
  2995. if s:tlist_{fidx}_tag_count == 0
  2996. return
  2997. endif
  2998. " Ignore all autocommands
  2999. let old_ei = &eventignore
  3000. set eventignore=all
  3001. " Save the original window number
  3002. let org_winnr = winnr()
  3003. if org_winnr == winnum
  3004. let in_taglist_window = 1
  3005. else
  3006. let in_taglist_window = 0
  3007. endif
  3008. " Go to the taglist window
  3009. if !in_taglist_window
  3010. exe winnum . 'wincmd w'
  3011. endif
  3012. " Clear previously selected name
  3013. match none
  3014. let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, a:cur_lnum)
  3015. if tidx == -1
  3016. " Make sure the current tag line is visible in the taglist window.
  3017. " Calling the winline() function makes the line visible. Don't know
  3018. " of a better way to achieve this.
  3019. let lnum = line('.')
  3020. if lnum < s:tlist_{fidx}_start || lnum > s:tlist_{fidx}_end
  3021. " Move the cursor to the beginning of the file
  3022. exe s:tlist_{fidx}_start
  3023. endif
  3024. if foldclosed('.') != -1
  3025. .foldopen
  3026. endif
  3027. call winline()
  3028. if !in_taglist_window
  3029. exe org_winnr . 'wincmd w'
  3030. endif
  3031. " Restore the autocommands
  3032. let &eventignore = old_ei
  3033. return
  3034. endif
  3035. " Extract the tag type
  3036. let ttype = s:Tlist_Get_Tag_Type_By_Tag(fidx, tidx)
  3037. " Compute the line number
  3038. " Start of file + Start of tag type + offset
  3039. let lnum = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset +
  3040. \ s:tlist_{fidx}_{tidx}_ttype_idx
  3041. " Goto the line containing the tag
  3042. exe lnum
  3043. " Open the fold
  3044. if foldclosed('.') != -1
  3045. .foldopen
  3046. endif
  3047. if a:center
  3048. " Move the tag line to the center of the taglist window
  3049. normal! z.
  3050. else
  3051. " Make sure the current tag line is visible in the taglist window.
  3052. " Calling the winline() function makes the line visible. Don't know
  3053. " of a better way to achieve this.
  3054. call winline()
  3055. endif
  3056. " Highlight the tag name
  3057. call s:Tlist_Window_Highlight_Line()
  3058. " Go back to the original window
  3059. if !in_taglist_window
  3060. exe org_winnr . 'wincmd w'
  3061. endif
  3062. " Restore the autocommands
  3063. let &eventignore = old_ei
  3064. return
  3065. endfunction
  3066. " Tlist_Get_Tag_Prototype_By_Line
  3067. " Get the prototype for the tag on or before the specified line number in the
  3068. " current buffer
  3069. function! Tlist_Get_Tag_Prototype_By_Line(...)
  3070. if a:0 == 0
  3071. " Arguments are not supplied. Use the current buffer name
  3072. " and line number
  3073. let filename = bufname('%')
  3074. let linenr = line('.')
  3075. elseif a:0 == 2
  3076. " Filename and line number are specified
  3077. let filename = a:1
  3078. let linenr = a:2
  3079. if linenr !~ '\d\+'
  3080. " Invalid line number
  3081. return ""
  3082. endif
  3083. else
  3084. " Sufficient arguments are not supplied
  3085. let msg = 'Usage: Tlist_Get_Tag_Prototype_By_Line <filename> ' .
  3086. \ '<line_number>'
  3087. call s:Tlist_Warning_Msg(msg)
  3088. return ""
  3089. endif
  3090. " Expand the file to a fully qualified name
  3091. let filename = fnamemodify(filename, ':p')
  3092. if filename == ''
  3093. return ""
  3094. endif
  3095. let fidx = s:Tlist_Get_File_Index(filename)
  3096. if fidx == -1
  3097. return ""
  3098. endif
  3099. " If there are no tags for this file, then no need to proceed further
  3100. if s:tlist_{fidx}_tag_count == 0
  3101. return ""
  3102. endif
  3103. " Get the tag text using the line number
  3104. let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
  3105. if tidx == -1
  3106. return ""
  3107. endif
  3108. return s:Tlist_Get_Tag_Prototype(fidx, tidx)
  3109. endfunction
  3110. " Tlist_Get_Tagname_By_Line
  3111. " Get the tag name on or before the specified line number in the
  3112. " current buffer
  3113. function! Tlist_Get_Tagname_By_Line(...)
  3114. if a:0 == 0
  3115. " Arguments are not supplied. Use the current buffer name
  3116. " and line number
  3117. let filename = bufname('%')
  3118. let linenr = line('.')
  3119. elseif a:0 == 2
  3120. " Filename and line number are specified
  3121. let filename = a:1
  3122. let linenr = a:2
  3123. if linenr !~ '\d\+'
  3124. " Invalid line number
  3125. return ""
  3126. endif
  3127. else
  3128. " Sufficient arguments are not supplied
  3129. let msg = 'Usage: Tlist_Get_Tagname_By_Line <filename> <line_number>'
  3130. call s:Tlist_Warning_Msg(msg)
  3131. return ""
  3132. endif
  3133. " Make sure the current file has a name
  3134. let filename = fnamemodify(filename, ':p')
  3135. if filename == ''
  3136. return ""
  3137. endif
  3138. let fidx = s:Tlist_Get_File_Index(filename)
  3139. if fidx == -1
  3140. return ""
  3141. endif
  3142. " If there are no tags for this file, then no need to proceed further
  3143. if s:tlist_{fidx}_tag_count == 0
  3144. return ""
  3145. endif
  3146. " Get the tag name using the line number
  3147. let tidx = s:Tlist_Find_Nearest_Tag_Idx(fidx, linenr)
  3148. if tidx == -1
  3149. return ""
  3150. endif
  3151. return s:tlist_{fidx}_{tidx}_tag_name
  3152. endfunction
  3153. " Tlist_Window_Move_To_File
  3154. " Move the cursor to the beginning of the current file or the next file
  3155. " or the previous file in the taglist window
  3156. " dir == -1, move to start of current or previous function
  3157. " dir == 1, move to start of next function
  3158. function! s:Tlist_Window_Move_To_File(dir)
  3159. if foldlevel('.') == 0
  3160. " Cursor is on a non-folded line (it is not in any of the files)
  3161. " Move it to a folded line
  3162. if a:dir == -1
  3163. normal! zk
  3164. else
  3165. " While moving down to the start of the next fold,
  3166. " no need to do go to the start of the next file.
  3167. normal! zj
  3168. return
  3169. endif
  3170. endif
  3171. let fidx = s:Tlist_Window_Get_File_Index_By_Linenum(line('.'))
  3172. if fidx == -1
  3173. return
  3174. endif
  3175. let cur_lnum = line('.')
  3176. if a:dir == -1
  3177. if cur_lnum > s:tlist_{fidx}_start
  3178. " Move to the beginning of the current file
  3179. exe s:tlist_{fidx}_start
  3180. return
  3181. endif
  3182. if fidx != 0
  3183. " Move to the beginning of the previous file
  3184. let fidx = fidx - 1
  3185. else
  3186. " Cursor is at the first file, wrap around to the last file
  3187. let fidx = s:tlist_file_count - 1
  3188. endif
  3189. exe s:tlist_{fidx}_start
  3190. return
  3191. else
  3192. " Move to the beginning of the next file
  3193. let fidx = fidx + 1
  3194. if fidx >= s:tlist_file_count
  3195. " Cursor is at the last file, wrap around to the first file
  3196. let fidx = 0
  3197. endif
  3198. if s:tlist_{fidx}_start != 0
  3199. exe s:tlist_{fidx}_start
  3200. endif
  3201. return
  3202. endif
  3203. endfunction
  3204. " Tlist_Session_Load
  3205. " Load a taglist session (information about all the displayed files
  3206. " and the tags) from the specified file
  3207. function! s:Tlist_Session_Load(...)
  3208. if a:0 == 0 || a:1 == ''
  3209. call s:Tlist_Warning_Msg('Usage: TlistSessionLoad <filename>')
  3210. return
  3211. endif
  3212. let sessionfile = a:1
  3213. if !filereadable(sessionfile)
  3214. let msg = 'Taglist: Error - Unable to open file ' . sessionfile
  3215. call s:Tlist_Warning_Msg(msg)
  3216. return
  3217. endif
  3218. " Mark the current window as the file window
  3219. call s:Tlist_Window_Mark_File_Window()
  3220. " Source the session file
  3221. exe 'source ' . sessionfile
  3222. let new_file_count = g:tlist_file_count
  3223. unlet! g:tlist_file_count
  3224. let i = 0
  3225. while i < new_file_count
  3226. let ftype = g:tlist_{i}_filetype
  3227. unlet! g:tlist_{i}_filetype
  3228. if !exists('s:tlist_' . ftype . '_count')
  3229. if s:Tlist_FileType_Init(ftype) == 0
  3230. let i = i + 1
  3231. continue
  3232. endif
  3233. endif
  3234. let fname = g:tlist_{i}_filename
  3235. unlet! g:tlist_{i}_filename
  3236. let fidx = s:Tlist_Get_File_Index(fname)
  3237. if fidx != -1
  3238. let s:tlist_{fidx}_visible = 0
  3239. let i = i + 1
  3240. continue
  3241. else
  3242. " As we are loading the tags from the session file, if this
  3243. " file was previously deleted by the user, now we need to
  3244. " add it back. So remove the file from the deleted list.
  3245. call s:Tlist_Update_Remove_List(fname, 0)
  3246. endif
  3247. let fidx = s:Tlist_Init_File(fname, ftype)
  3248. let s:tlist_{fidx}_filename = fname
  3249. let s:tlist_{fidx}_sort_type = g:tlist_{i}_sort_type
  3250. unlet! g:tlist_{i}_sort_type
  3251. let s:tlist_{fidx}_filetype = ftype
  3252. let s:tlist_{fidx}_mtime = getftime(fname)
  3253. let s:tlist_{fidx}_start = 0
  3254. let s:tlist_{fidx}_end = 0
  3255. let s:tlist_{fidx}_valid = 1
  3256. let s:tlist_{fidx}_tag_count = g:tlist_{i}_tag_count
  3257. unlet! g:tlist_{i}_tag_count
  3258. let j = 1
  3259. while j <= s:tlist_{fidx}_tag_count
  3260. let s:tlist_{fidx}_{j}_tag = g:tlist_{i}_{j}_tag
  3261. let s:tlist_{fidx}_{j}_tag_name = g:tlist_{i}_{j}_tag_name
  3262. let s:tlist_{fidx}_{j}_ttype_idx = g:tlist_{i}_{j}_ttype_idx
  3263. unlet! g:tlist_{i}_{j}_tag
  3264. unlet! g:tlist_{i}_{j}_tag_name
  3265. unlet! g:tlist_{i}_{j}_ttype_idx
  3266. let j = j + 1
  3267. endwhile
  3268. let j = 1
  3269. while j <= s:tlist_{ftype}_count
  3270. let ttype = s:tlist_{ftype}_{j}_name
  3271. if exists('g:tlist_' . i . '_' . ttype)
  3272. let s:tlist_{fidx}_{ttype} = g:tlist_{i}_{ttype}
  3273. unlet! g:tlist_{i}_{ttype}
  3274. let s:tlist_{fidx}_{ttype}_offset = 0
  3275. let s:tlist_{fidx}_{ttype}_count = g:tlist_{i}_{ttype}_count
  3276. unlet! g:tlist_{i}_{ttype}_count
  3277. let k = 1
  3278. while k <= s:tlist_{fidx}_{ttype}_count
  3279. let s:tlist_{fidx}_{ttype}_{k} = g:tlist_{i}_{ttype}_{k}
  3280. unlet! g:tlist_{i}_{ttype}_{k}
  3281. let k = k + 1
  3282. endwhile
  3283. else
  3284. let s:tlist_{fidx}_{ttype} = ''
  3285. let s:tlist_{fidx}_{ttype}_offset = 0
  3286. let s:tlist_{fidx}_{ttype}_count = 0
  3287. endif
  3288. let j = j + 1
  3289. endwhile
  3290. let i = i + 1
  3291. endwhile
  3292. " If the taglist window is open, then update it
  3293. let winnum = bufwinnr(g:TagList_title)
  3294. if winnum != -1
  3295. let save_winnr = winnr()
  3296. " Goto the taglist window
  3297. call s:Tlist_Window_Goto_Window()
  3298. " Refresh the taglist window
  3299. call s:Tlist_Window_Refresh()
  3300. " Go back to the original window
  3301. if save_winnr != winnr()
  3302. call s:Tlist_Exe_Cmd_No_Acmds('wincmd p')
  3303. endif
  3304. endif
  3305. endfunction
  3306. " Tlist_Session_Save
  3307. " Save a taglist session (information about all the displayed files
  3308. " and the tags) into the specified file
  3309. function! s:Tlist_Session_Save(...)
  3310. if a:0 == 0 || a:1 == ''
  3311. call s:Tlist_Warning_Msg('Usage: TlistSessionSave <filename>')
  3312. return
  3313. endif
  3314. let sessionfile = a:1
  3315. if s:tlist_file_count == 0
  3316. " There is nothing to save
  3317. call s:Tlist_Warning_Msg('Warning: Taglist is empty. Nothing to save.')
  3318. return
  3319. endif
  3320. if filereadable(sessionfile)
  3321. let ans = input('Do you want to overwrite ' . sessionfile . ' (Y/N)?')
  3322. if ans !=? 'y'
  3323. return
  3324. endif
  3325. echo "\n"
  3326. endif
  3327. let old_verbose = &verbose
  3328. set verbose&vim
  3329. exe 'redir! > ' . sessionfile
  3330. silent! echo '" Taglist session file. This file is auto-generated.'
  3331. silent! echo '" File information'
  3332. silent! echo 'let tlist_file_count = ' . s:tlist_file_count
  3333. let i = 0
  3334. while i < s:tlist_file_count
  3335. " Store information about the file
  3336. silent! echo 'let tlist_' . i . "_filename = '" .
  3337. \ s:tlist_{i}_filename . "'"
  3338. silent! echo 'let tlist_' . i . '_sort_type = "' .
  3339. \ s:tlist_{i}_sort_type . '"'
  3340. silent! echo 'let tlist_' . i . '_filetype = "' .
  3341. \ s:tlist_{i}_filetype . '"'
  3342. silent! echo 'let tlist_' . i . '_tag_count = ' .
  3343. \ s:tlist_{i}_tag_count
  3344. " Store information about all the tags
  3345. let j = 1
  3346. while j <= s:tlist_{i}_tag_count
  3347. let txt = escape(s:tlist_{i}_{j}_tag, '"\\')
  3348. silent! echo 'let tlist_' . i . '_' . j . '_tag = "' . txt . '"'
  3349. silent! echo 'let tlist_' . i . '_' . j . '_tag_name = "' .
  3350. \ s:tlist_{i}_{j}_tag_name . '"'
  3351. silent! echo 'let tlist_' . i . '_' . j . '_ttype_idx' . ' = ' .
  3352. \ s:tlist_{i}_{j}_ttype_idx
  3353. let j = j + 1
  3354. endwhile
  3355. " Store information about all the tags grouped by their type
  3356. let ftype = s:tlist_{i}_filetype
  3357. let j = 1
  3358. while j <= s:tlist_{ftype}_count
  3359. let ttype = s:tlist_{ftype}_{j}_name
  3360. if s:tlist_{i}_{ttype}_count != 0
  3361. let txt = escape(s:tlist_{i}_{ttype}, '"\')
  3362. let txt = substitute(txt, "\n", "\\\\n", 'g')
  3363. silent! echo 'let tlist_' . i . '_' . ttype . ' = "' .
  3364. \ txt . '"'
  3365. silent! echo 'let tlist_' . i . '_' . ttype . '_count = ' .
  3366. \ s:tlist_{i}_{ttype}_count
  3367. let k = 1
  3368. while k <= s:tlist_{i}_{ttype}_count
  3369. silent! echo 'let tlist_' . i . '_' . ttype . '_' . k .
  3370. \ ' = ' . s:tlist_{i}_{ttype}_{k}
  3371. let k = k + 1
  3372. endwhile
  3373. endif
  3374. let j = j + 1
  3375. endwhile
  3376. silent! echo
  3377. let i = i + 1
  3378. endwhile
  3379. redir END
  3380. let &verbose = old_verbose
  3381. endfunction
  3382. " Tlist_Buffer_Removed
  3383. " A buffer is removed from the Vim buffer list. Remove the tags defined
  3384. " for that file
  3385. function! s:Tlist_Buffer_Removed(filename)
  3386. call s:Tlist_Log_Msg('Tlist_Buffer_Removed (' . a:filename . ')')
  3387. " Make sure a valid filename is supplied
  3388. if a:filename == ''
  3389. return
  3390. endif
  3391. " Get tag list index of the specified file
  3392. let fidx = s:Tlist_Get_File_Index(a:filename)
  3393. if fidx == -1
  3394. " File not present in the taglist
  3395. return
  3396. endif
  3397. " Remove the file from the list
  3398. call s:Tlist_Remove_File(fidx, 0)
  3399. endfunction
  3400. " When a buffer is deleted, remove the file from the taglist
  3401. autocmd BufDelete * silent call s:Tlist_Buffer_Removed(expand('<afile>:p'))
  3402. " Tlist_Window_Open_File_Fold
  3403. " Open the fold for the specified file and close the fold for all the
  3404. " other files
  3405. function! s:Tlist_Window_Open_File_Fold(acmd_bufnr)
  3406. call s:Tlist_Log_Msg('Tlist_Window_Open_File_Fold (' . a:acmd_bufnr . ')')
  3407. " Make sure the taglist window is present
  3408. let winnum = bufwinnr(g:TagList_title)
  3409. if winnum == -1
  3410. call s:Tlist_Warning_Msg('Taglist: Error - Taglist window is not open')
  3411. return
  3412. endif
  3413. " Save the original window number
  3414. let org_winnr = winnr()
  3415. if org_winnr == winnum
  3416. let in_taglist_window = 1
  3417. else
  3418. let in_taglist_window = 0
  3419. endif
  3420. if in_taglist_window
  3421. " When entering the taglist window, no need to update the folds
  3422. return
  3423. endif
  3424. " Go to the taglist window
  3425. if !in_taglist_window
  3426. call s:Tlist_Exe_Cmd_No_Acmds(winnum . 'wincmd w')
  3427. endif
  3428. " Close all the folds
  3429. silent! %foldclose
  3430. " Get tag list index of the specified file
  3431. let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p')
  3432. if filereadable(fname)
  3433. let fidx = s:Tlist_Get_File_Index(fname)
  3434. if fidx != -1
  3435. " Open the fold for the file
  3436. exe "silent! " . s:tlist_{fidx}_start . "," .
  3437. \ s:tlist_{fidx}_end . "foldopen"
  3438. endif
  3439. endif
  3440. " Go back to the original window
  3441. if !in_taglist_window
  3442. call s:Tlist_Exe_Cmd_No_Acmds(org_winnr . 'wincmd w')
  3443. endif
  3444. endfunction
  3445. " Tlist_Window_Check_Auto_Open
  3446. " Open the taglist window automatically on Vim startup.
  3447. " Open the window only when files present in any of the Vim windows support
  3448. " tags.
  3449. function! s:Tlist_Window_Check_Auto_Open()
  3450. let open_window = 0
  3451. let i = 1
  3452. let buf_num = winbufnr(i)
  3453. while buf_num != -1
  3454. let filename = fnamemodify(bufname(buf_num), ':p')
  3455. let ft = s:Tlist_Get_Buffer_Filetype(buf_num)
  3456. if !s:Tlist_Skip_File(filename, ft)
  3457. let open_window = 1
  3458. break
  3459. endif
  3460. let i = i + 1
  3461. let buf_num = winbufnr(i)
  3462. endwhile
  3463. if open_window
  3464. call s:Tlist_Window_Toggle()
  3465. endif
  3466. endfunction
  3467. " Tlist_Refresh_Folds
  3468. " Remove and create the folds for all the files displayed in the taglist
  3469. " window. Used after entering a tab. If this is not done, then the folds
  3470. " are not properly created for taglist windows displayed in multiple tabs.
  3471. function! s:Tlist_Refresh_Folds()
  3472. let winnum = bufwinnr(g:TagList_title)
  3473. if winnum == -1
  3474. return
  3475. endif
  3476. let save_wnum = winnr()
  3477. exe winnum . 'wincmd w'
  3478. " First remove all the existing folds
  3479. normal! zE
  3480. " Create the folds for each in the tag list
  3481. let fidx = 0
  3482. while fidx < s:tlist_file_count
  3483. let ftype = s:tlist_{fidx}_filetype
  3484. " Create the folds for each tag type in a file
  3485. let j = 1
  3486. while j <= s:tlist_{ftype}_count
  3487. let ttype = s:tlist_{ftype}_{j}_name
  3488. if s:tlist_{fidx}_{ttype}_count
  3489. let s = s:tlist_{fidx}_start + s:tlist_{fidx}_{ttype}_offset
  3490. let e = s + s:tlist_{fidx}_{ttype}_count
  3491. exe s . ',' . e . 'fold'
  3492. endif
  3493. let j = j + 1
  3494. endwhile
  3495. exe s:tlist_{fidx}_start . ',' . s:tlist_{fidx}_end . 'fold'
  3496. exe 'silent! ' . s:tlist_{fidx}_start . ',' .
  3497. \ s:tlist_{fidx}_end . 'foldopen!'
  3498. let fidx = fidx + 1
  3499. endwhile
  3500. exe save_wnum . 'wincmd w'
  3501. endfunction
  3502. function! s:Tlist_Menu_Add_Base_Menu()
  3503. call s:Tlist_Log_Msg('Adding the base menu')
  3504. " Add the menu
  3505. anoremenu <silent> T&ags.Refresh\ menu :call <SID>Tlist_Menu_Refresh()<CR>
  3506. anoremenu <silent> T&ags.Sort\ menu\ by.Name
  3507. \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
  3508. anoremenu <silent> T&ags.Sort\ menu\ by.Order
  3509. \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
  3510. anoremenu T&ags.-SEP1- :
  3511. if &mousemodel =~ 'popup'
  3512. anoremenu <silent> PopUp.T&ags.Refresh\ menu
  3513. \ :call <SID>Tlist_Menu_Refresh()<CR>
  3514. anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Name
  3515. \ :call <SID>Tlist_Change_Sort('menu', 'set', 'name')<CR>
  3516. anoremenu <silent> PopUp.T&ags.Sort\ menu\ by.Order
  3517. \ :call <SID>Tlist_Change_Sort('menu', 'set', 'order')<CR>
  3518. anoremenu PopUp.T&ags.-SEP1- :
  3519. endif
  3520. endfunction
  3521. let s:menu_char_prefix =
  3522. \ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  3523. " Tlist_Menu_Get_Tag_Type_Cmd
  3524. " Get the menu command for the specified tag type
  3525. " fidx - File type index
  3526. " ftype - File Type
  3527. " add_ttype_name - To add or not to add the tag type name to the menu entries
  3528. " ttype_idx - Tag type index
  3529. function! s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, ttype_idx)
  3530. " Curly brace variable name optimization
  3531. let ftype_ttype_idx = a:ftype . '_' . a:ttype_idx
  3532. let ttype = s:tlist_{ftype_ttype_idx}_name
  3533. if a:add_ttype_name
  3534. " If the tag type name contains space characters, escape it. This
  3535. " will be used to create the menu entries.
  3536. let ttype_fullname = escape(s:tlist_{ftype_ttype_idx}_fullname, ' ')
  3537. endif
  3538. " Curly brace variable name optimization
  3539. let fidx_ttype = a:fidx . '_' . ttype
  3540. " Number of tag entries for this tag type
  3541. let tcnt = s:tlist_{fidx_ttype}_count
  3542. if tcnt == 0 " No entries for this tag type
  3543. return ''
  3544. endif
  3545. let mcmd = ''
  3546. " Create the menu items for the tags.
  3547. " Depending on the number of tags of this type, split the menu into
  3548. " multiple sub-menus, if needed.
  3549. if tcnt > g:Tlist_Max_Submenu_Items
  3550. let j = 1
  3551. while j <= tcnt
  3552. let final_index = j + g:Tlist_Max_Submenu_Items - 1
  3553. if final_index > tcnt
  3554. let final_index = tcnt
  3555. endif
  3556. " Extract the first and last tag name and form the
  3557. " sub-menu name
  3558. let tidx = s:tlist_{fidx_ttype}_{j}
  3559. let first_tag = s:tlist_{a:fidx}_{tidx}_tag_name
  3560. let tidx = s:tlist_{fidx_ttype}_{final_index}
  3561. let last_tag = s:tlist_{a:fidx}_{tidx}_tag_name
  3562. " Truncate the names, if they are greater than the
  3563. " max length
  3564. let first_tag = strpart(first_tag, 0, g:Tlist_Max_Tag_Length)
  3565. let last_tag = strpart(last_tag, 0, g:Tlist_Max_Tag_Length)
  3566. " Form the menu command prefix
  3567. let m_prefix = 'anoremenu <silent> T\&ags.'
  3568. if a:add_ttype_name
  3569. let m_prefix = m_prefix . ttype_fullname . '.'
  3570. endif
  3571. let m_prefix = m_prefix . first_tag . '\.\.\.' . last_tag . '.'
  3572. " Character prefix used to number the menu items (hotkey)
  3573. let m_prefix_idx = 0
  3574. while j <= final_index
  3575. let tidx = s:tlist_{fidx_ttype}_{j}
  3576. let tname = s:tlist_{a:fidx}_{tidx}_tag_name
  3577. let mcmd = mcmd . m_prefix . '\&' .
  3578. \ s:menu_char_prefix[m_prefix_idx] . '\.' .
  3579. \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' .
  3580. \ tidx . ')<CR>|'
  3581. let m_prefix_idx = m_prefix_idx + 1
  3582. let j = j + 1
  3583. endwhile
  3584. endwhile
  3585. else
  3586. " Character prefix used to number the menu items (hotkey)
  3587. let m_prefix_idx = 0
  3588. let m_prefix = 'anoremenu <silent> T\&ags.'
  3589. if a:add_ttype_name
  3590. let m_prefix = m_prefix . ttype_fullname . '.'
  3591. endif
  3592. let j = 1
  3593. while j <= tcnt
  3594. let tidx = s:tlist_{fidx_ttype}_{j}
  3595. let tname = s:tlist_{a:fidx}_{tidx}_tag_name
  3596. let mcmd = mcmd . m_prefix . '\&' .
  3597. \ s:menu_char_prefix[m_prefix_idx] . '\.' .
  3598. \ tname . ' :call <SID>Tlist_Menu_Jump_To_Tag(' . tidx
  3599. \ . ')<CR>|'
  3600. let m_prefix_idx = m_prefix_idx + 1
  3601. let j = j + 1
  3602. endwhile
  3603. endif
  3604. return mcmd
  3605. endfunction
  3606. " Update the taglist menu with the tags for the specified file
  3607. function! s:Tlist_Menu_File_Refresh(fidx)
  3608. call s:Tlist_Log_Msg('Refreshing the tag menu for ' . s:tlist_{a:fidx}_filename)
  3609. " The 'B' flag is needed in the 'cpoptions' option
  3610. let old_cpoptions = &cpoptions
  3611. set cpoptions&vim
  3612. exe s:tlist_{a:fidx}_menu_cmd
  3613. " Update the popup menu (if enabled)
  3614. if &mousemodel =~ 'popup'
  3615. let cmd = substitute(s:tlist_{a:fidx}_menu_cmd, ' T\\&ags\.',
  3616. \ ' PopUp.T\\\&ags.', "g")
  3617. exe cmd
  3618. endif
  3619. " The taglist menu is not empty now
  3620. let s:tlist_menu_empty = 0
  3621. " Restore the 'cpoptions' settings
  3622. let &cpoptions = old_cpoptions
  3623. endfunction
  3624. " Tlist_Menu_Update_File
  3625. " Add the taglist menu
  3626. function! s:Tlist_Menu_Update_File(clear_menu)
  3627. if !has('gui_running')
  3628. " Not running in GUI mode
  3629. return
  3630. endif
  3631. call s:Tlist_Log_Msg('Updating the tag menu, clear_menu = ' . a:clear_menu)
  3632. " Remove the tags menu
  3633. if a:clear_menu
  3634. call s:Tlist_Menu_Remove_File()
  3635. endif
  3636. " Skip buffers with 'buftype' set to nofile, nowrite, quickfix or help
  3637. if &buftype != ''
  3638. return
  3639. endif
  3640. let filename = fnamemodify(bufname('%'), ':p')
  3641. let ftype = s:Tlist_Get_Buffer_Filetype('%')
  3642. " If the file doesn't support tag listing, skip it
  3643. if s:Tlist_Skip_File(filename, ftype)
  3644. return
  3645. endif
  3646. let fidx = s:Tlist_Get_File_Index(filename)
  3647. if fidx == -1 || !s:tlist_{fidx}_valid
  3648. " Check whether this file is removed based on user request
  3649. " If it is, then don't display the tags for this file
  3650. if s:Tlist_User_Removed_File(filename)
  3651. return
  3652. endif
  3653. " Process the tags for the file
  3654. let fidx = s:Tlist_Process_File(filename, ftype)
  3655. if fidx == -1
  3656. return
  3657. endif
  3658. endif
  3659. let fname = escape(fnamemodify(bufname('%'), ':t'), '.')
  3660. if fname != ''
  3661. exe 'anoremenu T&ags.' . fname . ' <Nop>'
  3662. anoremenu T&ags.-SEP2- :
  3663. endif
  3664. if !s:tlist_{fidx}_tag_count
  3665. return
  3666. endif
  3667. if s:tlist_{fidx}_menu_cmd != ''
  3668. " Update the menu with the cached command
  3669. call s:Tlist_Menu_File_Refresh(fidx)
  3670. return
  3671. endif
  3672. " We are going to add entries to the tags menu, so the menu won't be
  3673. " empty
  3674. let s:tlist_menu_empty = 0
  3675. let cmd = ''
  3676. " Determine whether the tag type name needs to be added to the menu
  3677. " If more than one tag type is present in the taglisting for a file,
  3678. " then the tag type name needs to be present
  3679. let add_ttype_name = -1
  3680. let i = 1
  3681. while i <= s:tlist_{ftype}_count && add_ttype_name < 1
  3682. let ttype = s:tlist_{ftype}_{i}_name
  3683. if s:tlist_{fidx}_{ttype}_count
  3684. let add_ttype_name = add_ttype_name + 1
  3685. endif
  3686. let i = i + 1
  3687. endwhile
  3688. " Process the tags by the tag type and get the menu command
  3689. let i = 1
  3690. while i <= s:tlist_{ftype}_count
  3691. let mcmd = s:Tlist_Menu_Get_Tag_Type_Cmd(fidx, ftype, add_ttype_name, i)
  3692. if mcmd != ''
  3693. let cmd = cmd . mcmd
  3694. endif
  3695. let i = i + 1
  3696. endwhile
  3697. " Cache the menu command for reuse
  3698. let s:tlist_{fidx}_menu_cmd = cmd
  3699. " Update the menu
  3700. call s:Tlist_Menu_File_Refresh(fidx)
  3701. endfunction
  3702. " Tlist_Menu_Remove_File
  3703. " Remove the tags displayed in the tags menu
  3704. function! s:Tlist_Menu_Remove_File()
  3705. if !has('gui_running') || s:tlist_menu_empty
  3706. return
  3707. endif
  3708. call s:Tlist_Log_Msg('Removing the tags menu for a file')
  3709. " Cleanup the Tags menu
  3710. silent! unmenu T&ags
  3711. if &mousemodel =~ 'popup'
  3712. silent! unmenu PopUp.T&ags
  3713. endif
  3714. " Add a dummy menu item to retain teared off menu
  3715. noremenu T&ags.Dummy l
  3716. silent! unmenu! T&ags
  3717. if &mousemodel =~ 'popup'
  3718. silent! unmenu! PopUp.T&ags
  3719. endif
  3720. call s:Tlist_Menu_Add_Base_Menu()
  3721. " Remove the dummy menu item
  3722. unmenu T&ags.Dummy
  3723. let s:tlist_menu_empty = 1
  3724. endfunction
  3725. " Tlist_Menu_Refresh
  3726. " Refresh the taglist menu
  3727. function! s:Tlist_Menu_Refresh()
  3728. call s:Tlist_Log_Msg('Refreshing the tags menu')
  3729. let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
  3730. if fidx != -1
  3731. " Invalidate the cached menu command
  3732. let s:tlist_{fidx}_menu_cmd = ''
  3733. endif
  3734. " Update the taglist, menu and window
  3735. call s:Tlist_Update_Current_File()
  3736. endfunction
  3737. " Tlist_Menu_Jump_To_Tag
  3738. " Jump to the selected tag
  3739. function! s:Tlist_Menu_Jump_To_Tag(tidx)
  3740. let fidx = s:Tlist_Get_File_Index(fnamemodify(bufname('%'), ':p'))
  3741. if fidx == -1
  3742. return
  3743. endif
  3744. let tagpat = s:Tlist_Get_Tag_SearchPat(fidx, a:tidx)
  3745. if tagpat == ''
  3746. return
  3747. endif
  3748. " Add the current cursor position to the jump list, so that user can
  3749. " jump back using the ' and ` marks.
  3750. mark '
  3751. silent call search(tagpat, 'w')
  3752. " Bring the line to the middle of the window
  3753. normal! z.
  3754. " If the line is inside a fold, open the fold
  3755. if foldclosed('.') != -1
  3756. .foldopen
  3757. endif
  3758. endfunction
  3759. " Tlist_Menu_Init
  3760. " Initialize the taglist menu
  3761. function! s:Tlist_Menu_Init()
  3762. call s:Tlist_Menu_Add_Base_Menu()
  3763. " Automatically add the tags defined in the current file to the menu
  3764. augroup TagListMenuCmds
  3765. autocmd!
  3766. if !g:Tlist_Process_File_Always
  3767. autocmd BufEnter * call s:Tlist_Refresh()
  3768. endif
  3769. autocmd BufLeave * call s:Tlist_Menu_Remove_File()
  3770. augroup end
  3771. call s:Tlist_Menu_Update_File(0)
  3772. endfunction
  3773. " Tlist_Vim_Session_Load
  3774. " Initialize the taglist window/buffer, which is created when loading
  3775. " a Vim session file.
  3776. function! s:Tlist_Vim_Session_Load()
  3777. call s:Tlist_Log_Msg('Tlist_Vim_Session_Load')
  3778. " Initialize the taglist window
  3779. call s:Tlist_Window_Init()
  3780. " Refresh the taglist window
  3781. call s:Tlist_Window_Refresh()
  3782. endfunction
  3783. " Tlist_Set_App
  3784. " Set the name of the external plugin/application to which taglist
  3785. " belongs.
  3786. " Taglist plugin is part of another plugin like cream or winmanager.
  3787. function! Tlist_Set_App(name)
  3788. if a:name == ""
  3789. return
  3790. endif
  3791. let s:tlist_app_name = a:name
  3792. endfunction
  3793. " Winmanager integration
  3794. " Initialization required for integration with winmanager
  3795. function! TagList_Start()
  3796. " If current buffer is not taglist buffer, then don't proceed
  3797. if bufname('%') != '__Tag_List__'
  3798. return
  3799. endif
  3800. call Tlist_Set_App('winmanager')
  3801. " Get the current filename from the winmanager plugin
  3802. let bufnum = WinManagerGetLastEditedFile()
  3803. if bufnum != -1
  3804. let filename = fnamemodify(bufname(bufnum), ':p')
  3805. let ftype = s:Tlist_Get_Buffer_Filetype(bufnum)
  3806. endif
  3807. " Initialize the taglist window, if it is not already initialized
  3808. if !exists('s:tlist_window_initialized') || !s:tlist_window_initialized
  3809. call s:Tlist_Window_Init()
  3810. call s:Tlist_Window_Refresh()
  3811. let s:tlist_window_initialized = 1
  3812. endif
  3813. " Update the taglist window
  3814. if bufnum != -1
  3815. if !s:Tlist_Skip_File(filename, ftype) && g:Tlist_Auto_Update
  3816. call s:Tlist_Window_Refresh_File(filename, ftype)
  3817. endif
  3818. endif
  3819. endfunction
  3820. function! TagList_IsValid()
  3821. return 0
  3822. endfunction
  3823. function! TagList_WrapUp()
  3824. return 0
  3825. endfunction
  3826. " restore 'cpo'
  3827. let &cpo = s:cpo_save
  3828. unlet s:cpo_save