rst.el 163 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619
  1. ;;; rst.el --- Mode for viewing and editing reStructuredText-documents -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
  3. ;; Maintainer: Stefan Merten <stefan at merten-home dot de>
  4. ;; Author: Stefan Merten <stefan at merten-home dot de>,
  5. ;; Martin Blais <blais@furius.ca>,
  6. ;; David Goodger <goodger@python.org>,
  7. ;; Wei-Wei Guo <wwguocn@gmail.com>
  8. ;; This file is part of GNU Emacs.
  9. ;; GNU Emacs is free software: you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation, either version 3 of the License, or
  12. ;; (at your option) any later version.
  13. ;; GNU Emacs is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  19. ;;; Commentary:
  20. ;; This package provides major mode rst-mode, which supports documents marked
  21. ;; up using the reStructuredText format. Support includes font locking as well
  22. ;; as a lot of convenience functions for editing. It does this by defining a
  23. ;; Emacs major mode: rst-mode (ReST). This mode is derived from text-mode.
  24. ;; This package also contains:
  25. ;;
  26. ;; - Functions to automatically adjust and cycle the section underline
  27. ;; adornments;
  28. ;; - A mode that displays the table of contents and allows you to jump anywhere
  29. ;; from it;
  30. ;; - Functions to insert and automatically update a TOC in your source
  31. ;; document;
  32. ;; - Function to insert list, processing item bullets and enumerations
  33. ;; automatically;
  34. ;; - Font-lock highlighting of most reStructuredText structures;
  35. ;; - Indentation and filling according to reStructuredText syntax;
  36. ;; - Cursor movement according to reStructuredText syntax;
  37. ;; - Some other convenience functions.
  38. ;;
  39. ;; See the accompanying document in the docutils documentation about
  40. ;; the contents of this package and how to use it.
  41. ;;
  42. ;; For more information about reStructuredText, see
  43. ;; http://docutils.sourceforge.net/rst.html
  44. ;;
  45. ;; For full details on how to use the contents of this file, see
  46. ;; http://docutils.sourceforge.net/docs/user/emacs.html
  47. ;;
  48. ;; There are a number of convenient key bindings provided by rst-mode. For the
  49. ;; bindings, try C-c C-h when in rst-mode. There are also many variables that
  50. ;; can be customized, look for defcustom in this file or look for the "rst"
  51. ;; customization group contained in the "wp" group.
  52. ;;
  53. ;; If you use the table-of-contents feature, you may want to add a hook to
  54. ;; update the TOC automatically every time you adjust a section title::
  55. ;;
  56. ;; (add-hook 'rst-adjust-hook 'rst-toc-update)
  57. ;;
  58. ;; Syntax highlighting: font-lock is enabled by default. If you want to turn
  59. ;; off syntax highlighting to rst-mode, you can use the following::
  60. ;;
  61. ;; (setq font-lock-global-modes '(not rst-mode ...))
  62. ;;
  63. ;;; DOWNLOAD
  64. ;; The latest release of this file lies in the docutils source code repository:
  65. ;; http://docutils.svn.sourceforge.net/svnroot/docutils/trunk/docutils/tools/editors/emacs/rst.el
  66. ;;; INSTALLATION
  67. ;; Add the following lines to your init file:
  68. ;;
  69. ;; (require 'rst)
  70. ;;
  71. ;; If you are using `.txt' as a standard extension for reST files as
  72. ;; http://docutils.sourceforge.net/FAQ.html#what-s-the-standard-filename-extension-for-a-restructuredtext-file
  73. ;; suggests you may use one of the `Local Variables in Files' mechanism Emacs
  74. ;; provides to set the major mode automatically. For instance you may use::
  75. ;;
  76. ;; .. -*- mode: rst -*-
  77. ;;
  78. ;; in the very first line of your file. The following code is useful if you
  79. ;; want automatically enter rst-mode from any file with compatible extensions:
  80. ;;
  81. ;; (setq auto-mode-alist
  82. ;; (append '(("\\.txt\\'" . rst-mode)
  83. ;; ("\\.rst\\'" . rst-mode)
  84. ;; ("\\.rest\\'" . rst-mode)) auto-mode-alist))
  85. ;;
  86. ;;; Code:
  87. ;; FIXME: Check through major mode conventions again.
  88. ;; FIXME: Embed complicated `defconst's in `eval-when-compile'.
  89. ;; Common Lisp stuff
  90. (require 'cl-lib)
  91. ;; Correct wrong declaration.
  92. (def-edebug-spec push
  93. (&or [form symbolp] [form gv-place]))
  94. ;; Correct wrong declaration. This still doesn't support dotted destructuring
  95. ;; though.
  96. (def-edebug-spec cl-lambda-list
  97. (([&rest cl-macro-arg]
  98. [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
  99. [&optional ["&rest" arg]]
  100. [&optional ["&key" [cl-&key-arg &rest cl-&key-arg]
  101. &optional "&allow-other-keys"]]
  102. [&optional ["&aux" &rest
  103. &or (symbolp &optional def-form) symbolp]]
  104. )))
  105. ;; Add missing declaration.
  106. (def-edebug-spec cl-type-spec sexp) ;; This is not exactly correct but good
  107. ;; enough.
  108. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  109. ;; Support for `testcover'
  110. (when (and (boundp 'testcover-1value-functions)
  111. (boundp 'testcover-compose-functions))
  112. ;; Below `lambda' is used in a loop with varying parameters and is thus not
  113. ;; 1valued.
  114. (setq testcover-1value-functions
  115. (delq 'lambda testcover-1value-functions))
  116. (add-to-list 'testcover-compose-functions 'lambda))
  117. (defun rst-testcover-defcustom ()
  118. "Remove all customized variables from `testcover-module-constants'.
  119. This seems to be a bug in `testcover': `defcustom' variables are
  120. considered constants. Revert it with this function after each `defcustom'."
  121. (when (boundp 'testcover-module-constants)
  122. (setq testcover-module-constants
  123. (delq nil
  124. (mapcar
  125. #'(lambda (sym)
  126. (if (not (plist-member (symbol-plist sym) 'standard-value))
  127. sym))
  128. testcover-module-constants)))))
  129. (defun rst-testcover-add-compose (fun)
  130. "Add FUN to `testcover-compose-functions'."
  131. (when (boundp 'testcover-compose-functions)
  132. (add-to-list 'testcover-compose-functions fun)))
  133. (defun rst-testcover-add-1value (fun)
  134. "Add FUN to `testcover-1value-functions'."
  135. (when (boundp 'testcover-1value-functions)
  136. (add-to-list 'testcover-1value-functions fun)))
  137. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  138. ;; Helpers.
  139. (cl-defmacro rst-destructuring-dolist
  140. ((arglist list &optional result) &rest body)
  141. "`cl-dolist' with destructuring of the list elements.
  142. ARGLIST is a Common List argument list which may include
  143. destructuring. LIST, RESULT and BODY are as for `cl-dolist'.
  144. Note that definitions in ARGLIST are visible only in the BODY and
  145. neither in RESULT nor in LIST."
  146. ;; FIXME: It would be very useful if the definitions in ARGLIST would be
  147. ;; visible in RESULT. But may be this is rather a
  148. ;; `rst-destructuring-do' then.
  149. (declare (debug
  150. (&define ([&or symbolp cl-macro-list] def-form &optional def-form)
  151. cl-declarations def-body))
  152. (indent 1))
  153. (let ((var (make-symbol "--rst-destructuring-dolist-var--")))
  154. `(cl-dolist (,var ,list ,result)
  155. (cl-destructuring-bind ,arglist ,var
  156. ,@body))))
  157. (defun rst-forward-line-strict (n &optional limit)
  158. ;; testcover: ok.
  159. "Try to move point to beginning of line I + N where I is the current line.
  160. Return t if movement is successful. Otherwise don't move point
  161. and return nil. If a position is given by LIMIT, movement
  162. happened but the following line is missing and thus its beginning
  163. can not be reached but the movement reached at least LIMIT
  164. consider this a successful movement. LIMIT is ignored in other
  165. cases."
  166. (let ((start (point)))
  167. (if (and (zerop (forward-line n))
  168. (or (bolp)
  169. (and limit
  170. (>= (point) limit))))
  171. t
  172. (goto-char start)
  173. nil)))
  174. (defun rst-forward-line-looking-at (n rst-re-args &optional fun)
  175. ;; testcover: ok.
  176. "Move forward N lines and if successful check whether RST-RE-ARGS is matched.
  177. Moving forward is done by `rst-forward-line-strict'. RST-RE-ARGS
  178. is a single or a list of arguments for `rst-re'. FUN is a
  179. function defaulting to `identity' which is called after the call
  180. to `looking-at' receiving its return value as the first argument.
  181. When FUN is called match data is just set by `looking-at' and
  182. point is at the beginning of the line. Return nil if moving
  183. forward failed or otherwise the return value of FUN. Preserve
  184. global match data, point, mark and current buffer."
  185. (unless (listp rst-re-args)
  186. (setq rst-re-args (list rst-re-args)))
  187. (unless fun
  188. (setq fun #'identity))
  189. (save-match-data
  190. (save-excursion
  191. (when (rst-forward-line-strict n)
  192. (funcall fun (looking-at (apply #'rst-re rst-re-args)))))))
  193. (rst-testcover-add-1value 'rst-delete-entire-line)
  194. (defun rst-delete-entire-line (n)
  195. "Move N lines and delete the entire line."
  196. (delete-region (line-beginning-position (+ n 1))
  197. (line-beginning-position (+ n 2))))
  198. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  199. ;; Versions
  200. (defun rst-extract-version (delim-re head-re re tail-re var &optional default)
  201. ;; testcover: ok.
  202. "Extract the version from a variable according to the given regexes.
  203. Return the version after regex DELIM-RE and HEAD-RE matching RE
  204. and before TAIL-RE and DELIM-RE in VAR or DEFAULT for no match."
  205. (if (string-match
  206. (concat delim-re head-re "\\(" re "\\)" tail-re delim-re)
  207. var)
  208. (match-string 1 var)
  209. default))
  210. ;; Use CVSHeader to really get information from CVS and not other version
  211. ;; control systems.
  212. (defconst rst-cvs-header
  213. "$CVSHeader: sm/rst_el/rst.el,v 1.1058.2.9 2017/01/08 09:54:50 stefan Exp $")
  214. (defconst rst-cvs-rev
  215. (rst-extract-version "\\$" "CVSHeader: \\S + " "[0-9]+\\(?:\\.[0-9]+\\)+"
  216. " .*" rst-cvs-header "0.0")
  217. "The CVS revision of this file. CVS revision is the development revision.")
  218. (defconst rst-cvs-timestamp
  219. (rst-extract-version "\\$" "CVSHeader: \\S + \\S + "
  220. "[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+" " .*"
  221. rst-cvs-header "1970-01-01 00:00:00")
  222. "The CVS time stamp of this file.")
  223. ;; Use LastChanged... to really get information from SVN.
  224. (defconst rst-svn-rev
  225. (rst-extract-version "\\$" "LastChangedRevision: " "[0-9]+" " "
  226. "$LastChangedRevision: 8015 $")
  227. "The SVN revision of this file.
  228. SVN revision is the upstream (docutils) revision.")
  229. (defconst rst-svn-timestamp
  230. (rst-extract-version "\\$" "LastChangedDate: " ".+?+" " "
  231. "$LastChangedDate: 2017-01-08 10:54:35 +0100 (Sun, 08 Jan 2017) $")
  232. "The SVN time stamp of this file.")
  233. ;; Maintained by the release process.
  234. (defconst rst-official-version
  235. (rst-extract-version "%" "OfficialVersion: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
  236. "%OfficialVersion: 1.5.2 %")
  237. "Official version of the package.")
  238. (defconst rst-official-cvs-rev
  239. (rst-extract-version "[%$]" "Revision: " "[0-9]+\\(?:\\.[0-9]+\\)+" " "
  240. "$Revision: 1.1058.2.9 $")
  241. "CVS revision of this file in the official version.")
  242. (defconst rst-version
  243. (if (equal rst-official-cvs-rev rst-cvs-rev)
  244. rst-official-version
  245. (format "%s (development %s [%s])" rst-official-version
  246. rst-cvs-rev rst-cvs-timestamp))
  247. "The version string.
  248. Starts with the current official version. For developer versions
  249. in parentheses follows the development revision and the time stamp.")
  250. (defconst rst-package-emacs-version-alist
  251. '(("1.0.0" . "24.3")
  252. ("1.1.0" . "24.3")
  253. ("1.2.0" . "24.3")
  254. ("1.2.1" . "24.3")
  255. ("1.3.0" . "24.3")
  256. ("1.3.1" . "24.3")
  257. ("1.4.0" . "24.3")
  258. ("1.4.1" . "25.1")
  259. ("1.4.2" . "25.1")
  260. ("1.5.0" . "26.1")
  261. ("1.5.1" . "26.1")
  262. ("1.5.2" . "26.1")
  263. ;; Whatever the Emacs version is this rst.el version ends up in.
  264. ))
  265. (unless (assoc rst-official-version rst-package-emacs-version-alist)
  266. (error "Version %s not listed in `rst-package-emacs-version-alist'"
  267. rst-version))
  268. (add-to-list 'customize-package-emacs-version-alist
  269. (cons 'ReST rst-package-emacs-version-alist))
  270. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  271. ;; Initialize customization
  272. (defgroup rst nil "Support for reStructuredText documents."
  273. :group 'text
  274. :version "23.1"
  275. :link '(url-link "http://docutils.sourceforge.net/rst.html"))
  276. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  277. ;; Facilities for regular expressions used everywhere
  278. ;; The trailing numbers in the names give the number of referenceable regex
  279. ;; groups contained in the regex.
  280. ;; Used to be customizable but really is not customizable but fixed by the reST
  281. ;; syntax.
  282. (defconst rst-bullets
  283. ;; Sorted so they can form a character class when concatenated.
  284. '(?- ?* ?+ ?• ?‣ ?⁃)
  285. "List of all possible bullet characters for bulleted lists.")
  286. (defconst rst-uri-schemes
  287. '("acap" "cid" "data" "dav" "fax" "file" "ftp" "gopher" "http" "https" "imap"
  288. "ldap" "mailto" "mid" "modem" "news" "nfs" "nntp" "pop" "prospero" "rtsp"
  289. "service" "sip" "tel" "telnet" "tip" "urn" "vemmi" "wais")
  290. "Supported URI schemes.")
  291. (defconst rst-adornment-chars
  292. ;; Sorted so they can form a character class when concatenated.
  293. '(?\]
  294. ?! ?\" ?# ?$ ?% ?& ?' ?\( ?\) ?* ?+ ?, ?. ?/ ?: ?\; ?< ?= ?> ?? ?@ ?\[ ?\\
  295. ?^ ?_ ?` ?{ ?| ?} ?~
  296. ?-)
  297. "Characters which may be used in adornments for sections and transitions.")
  298. (defconst rst-max-inline-length
  299. 1000
  300. "Maximum length of inline markup to recognize.")
  301. (defconst rst-re-alist-def
  302. ;; `*-beg' matches * at the beginning of a line.
  303. ;; `*-end' matches * at the end of a line.
  304. ;; `*-prt' matches a part of *.
  305. ;; `*-tag' matches *.
  306. ;; `*-sta' matches the start of * which may be followed by respective content.
  307. ;; `*-pfx' matches the delimiter left of *.
  308. ;; `*-sfx' matches the delimiter right of *.
  309. ;; `*-hlp' helper for *.
  310. ;;
  311. ;; A trailing number says how many referenceable groups are contained.
  312. `(
  313. ;; Horizontal white space (`hws')
  314. (hws-prt "[\t ]")
  315. (hws-tag hws-prt "*") ; Optional sequence of horizontal white space.
  316. (hws-sta hws-prt "+") ; Mandatory sequence of horizontal white space.
  317. ;; Lines (`lin')
  318. (lin-beg "^" hws-tag) ; Beginning of a possibly indented line.
  319. (lin-end hws-tag "$") ; End of a line with optional trailing white space.
  320. (linemp-tag "^" hws-tag "$") ; Empty line with optional white space.
  321. ;; Various tags and parts
  322. (ell-tag "\\.\\.\\.") ; Ellipsis
  323. (bul-tag ,(concat "[" rst-bullets "]")) ; A bullet.
  324. (ltr-tag "[a-zA-Z]") ; A letter enumerator tag.
  325. (num-prt "[0-9]") ; A number enumerator part.
  326. (num-tag num-prt "+") ; A number enumerator tag.
  327. (rom-prt "[IVXLCDMivxlcdm]") ; A roman enumerator part.
  328. (rom-tag rom-prt "+") ; A roman enumerator tag.
  329. (aut-tag "#") ; An automatic enumerator tag.
  330. (dcl-tag "::") ; Double colon.
  331. ;; Block lead in (`bli')
  332. (bli-sfx (:alt hws-sta "$")) ; Suffix of a block lead-in with *optional*
  333. ; immediate content.
  334. ;; Various starts
  335. (bul-sta bul-tag bli-sfx) ; Start of a bulleted item.
  336. (bul-beg lin-beg bul-sta) ; A bullet item at the beginning of a line.
  337. ;; Explicit markup tag (`exm')
  338. (exm-tag "\\.\\.")
  339. (exm-sta exm-tag hws-sta)
  340. (exm-beg lin-beg exm-sta)
  341. ;; Counters in enumerations (`cnt')
  342. (cntany-tag (:alt ltr-tag num-tag rom-tag aut-tag)) ; An arbitrary counter.
  343. (cntexp-tag (:alt ltr-tag num-tag rom-tag)) ; An arbitrary explicit counter.
  344. ;; Enumerator (`enm')
  345. (enmany-tag (:alt
  346. (:seq cntany-tag "\\.")
  347. (:seq "(?" cntany-tag ")"))) ; An arbitrary enumerator.
  348. (enmexp-tag (:alt
  349. (:seq cntexp-tag "\\.")
  350. (:seq "(?" cntexp-tag ")"))) ; An arbitrary explicit
  351. ; enumerator.
  352. (enmaut-tag (:alt
  353. (:seq aut-tag "\\.")
  354. (:seq "(?" aut-tag ")"))) ; An automatic enumerator.
  355. (enmany-sta enmany-tag bli-sfx) ; An arbitrary enumerator start.
  356. (enmexp-sta enmexp-tag bli-sfx) ; An arbitrary explicit enumerator start.
  357. (enmexp-beg lin-beg enmexp-sta) ; An arbitrary explicit enumerator start
  358. ; at the beginning of a line.
  359. ;; Items may be enumerated or bulleted (`itm')
  360. (itmany-tag (:alt enmany-tag bul-tag)) ; An arbitrary item tag.
  361. (itmany-sta-1 (:grp itmany-tag) bli-sfx) ; An arbitrary item start, group
  362. ; is the item tag.
  363. (itmany-beg-1 lin-beg itmany-sta-1) ; An arbitrary item start at the
  364. ; beginning of a line, group is the
  365. ; item tag.
  366. ;; Inline markup (`ilm')
  367. (ilm-pfx (:alt "^" hws-prt "[-'\"([{<‘“«’/:]"))
  368. (ilm-sfx (:alt "$" hws-prt "[]-'\")}>’”»/:.,;!?\\]"))
  369. ;; Inline markup content (`ilc')
  370. (ilcsgl-tag "\\S ") ; A single non-white character.
  371. (ilcast-prt (:alt "[^*\\]" "\\\\.")) ; Part of non-asterisk content.
  372. (ilcbkq-prt (:alt "[^`\\]" "\\\\.")) ; Part of non-backquote content.
  373. (ilcbkqdef-prt (:alt "[^`\\\n]" "\\\\.")) ; Part of non-backquote
  374. ; definition.
  375. (ilcbar-prt (:alt "[^|\\]" "\\\\.")) ; Part of non-vertical-bar content.
  376. (ilcbardef-prt (:alt "[^|\\\n]" "\\\\.")) ; Part of non-vertical-bar
  377. ; definition.
  378. (ilcast-sfx "[^\t *\\]") ; Suffix of non-asterisk content.
  379. (ilcbkq-sfx "[^\t `\\]") ; Suffix of non-backquote content.
  380. (ilcbar-sfx "[^\t |\\]") ; Suffix of non-vertical-bar content.
  381. (ilcrep-hlp ,(format "\\{0,%d\\}" rst-max-inline-length)) ; Repeat count.
  382. (ilcast-tag (:alt ilcsgl-tag
  383. (:seq ilcsgl-tag
  384. ilcast-prt ilcrep-hlp
  385. ilcast-sfx))) ; Non-asterisk content.
  386. (ilcbkq-tag (:alt ilcsgl-tag
  387. (:seq ilcsgl-tag
  388. ilcbkq-prt ilcrep-hlp
  389. ilcbkq-sfx))) ; Non-backquote content.
  390. (ilcbkqdef-tag (:alt ilcsgl-tag
  391. (:seq ilcsgl-tag
  392. ilcbkqdef-prt ilcrep-hlp
  393. ilcbkq-sfx))) ; Non-backquote definition.
  394. (ilcbar-tag (:alt ilcsgl-tag
  395. (:seq ilcsgl-tag
  396. ilcbar-prt ilcrep-hlp
  397. ilcbar-sfx))) ; Non-vertical-bar content.
  398. (ilcbardef-tag (:alt ilcsgl-tag
  399. (:seq ilcsgl-tag
  400. ilcbardef-prt ilcrep-hlp
  401. ilcbar-sfx))) ; Non-vertical-bar definition.
  402. ;; Fields (`fld')
  403. (fldnam-prt (:alt "[^:\n]" "\\\\:")) ; Part of a field name.
  404. (fldnam-tag fldnam-prt "+") ; A field name.
  405. (fld-tag ":" fldnam-tag ":") ; A field marker.
  406. ;; Options (`opt')
  407. (optsta-tag (:alt "[-+/]" "--")) ; Start of an option.
  408. (optnam-tag "\\sw" (:alt "-" "\\sw") "*") ; Name of an option.
  409. (optarg-tag (:shy "[ =]\\S +")) ; Option argument.
  410. (optsep-tag (:shy "," hws-prt)) ; Separator between options.
  411. (opt-tag (:shy optsta-tag optnam-tag optarg-tag "?")) ; A complete option.
  412. ;; Footnotes and citations (`fnc')
  413. (fncnam-prt "[^]\n]") ; Part of a footnote or citation name.
  414. (fncnam-tag fncnam-prt "+") ; A footnote or citation name.
  415. (fnc-tag "\\[" fncnam-tag "]") ; A complete footnote or citation tag.
  416. (fncdef-tag-2 (:grp exm-sta)
  417. (:grp fnc-tag)) ; A complete footnote or citation definition
  418. ; tag. First group is the explicit markup
  419. ; start, second group is the footnote /
  420. ; citation tag.
  421. (fnc-sta-2 fncdef-tag-2 bli-sfx) ; Start of a footnote or citation
  422. ; definition. First group is the explicit
  423. ; markup start, second group is the
  424. ; footnote / citation tag.
  425. ;; Substitutions (`sub')
  426. (sub-tag "|" ilcbar-tag "|") ; A complete substitution tag.
  427. (subdef-tag "|" ilcbardef-tag "|") ; A complete substitution definition
  428. ; tag.
  429. ;; Symbol (`sym')
  430. (sym-prt "[-+.:_]") ; Non-word part of a symbol.
  431. (sym-tag (:shy "\\sw+" (:shy sym-prt "\\sw+") "*"))
  432. ;; URIs (`uri')
  433. (uri-tag (:alt ,@rst-uri-schemes))
  434. ;; Adornment (`ado')
  435. (ado-prt "[" ,(concat rst-adornment-chars) "]")
  436. (adorep3-hlp "\\{3,\\}") ; There must be at least 3 characters because
  437. ; otherwise explicit markup start would be
  438. ; recognized.
  439. (adorep2-hlp "\\{2,\\}") ; As `adorep3-hlp' but when the first of three
  440. ; characters is matched differently.
  441. (ado-tag-1-1 (:grp ado-prt)
  442. "\\1" adorep2-hlp) ; A complete adornment, group is the first
  443. ; adornment character and MUST be the FIRST
  444. ; group in the whole expression.
  445. (ado-tag-1-2 (:grp ado-prt)
  446. "\\2" adorep2-hlp) ; A complete adornment, group is the first
  447. ; adornment character and MUST be the
  448. ; SECOND group in the whole expression.
  449. (ado-beg-2-1 "^" (:grp ado-tag-1-2)
  450. lin-end) ; A complete adornment line; first group is the whole
  451. ; adornment and MUST be the FIRST group in the whole
  452. ; expression; second group is the first adornment
  453. ; character.
  454. ;; Titles (`ttl')
  455. (ttl-tag "\\S *\\w.*\\S ") ; A title text.
  456. (ttl-beg-1 lin-beg (:grp ttl-tag)) ; A title text at the beginning of a
  457. ; line. First group is the complete,
  458. ; trimmed title text.
  459. ;; Directives and substitution definitions (`dir')
  460. (dir-tag-3 (:grp exm-sta)
  461. (:grp (:shy subdef-tag hws-sta) "?")
  462. (:grp sym-tag dcl-tag)) ; A directive or substitution definition
  463. ; tag. First group is explicit markup
  464. ; start, second group is a possibly
  465. ; empty substitution tag, third group is
  466. ; the directive tag including the double
  467. ; colon.
  468. (dir-sta-3 dir-tag-3 bli-sfx) ; Start of a directive or substitution
  469. ; definition. Groups are as in dir-tag-3.
  470. ;; Literal block (`lit')
  471. (lit-sta-2 (:grp (:alt "[^.\n]" "\\.[^.\n]") ".*") "?"
  472. (:grp dcl-tag) "$") ; Start of a literal block. First group is
  473. ; any text before the double colon tag which
  474. ; may not exist, second group is the double
  475. ; colon tag.
  476. ;; Comments (`cmt')
  477. (cmt-sta-1 (:grp exm-sta) "[^[|_\n]"
  478. (:alt "[^:\n]" (:seq ":" (:alt "[^:\n]" "$")))
  479. "*$") ; Start of a comment block; first group is explicit markup
  480. ; start.
  481. ;; Paragraphs (`par')
  482. (par-tag- (:alt itmany-tag fld-tag opt-tag fncdef-tag-2 dir-tag-3 exm-tag)
  483. ) ; Tag at the beginning of a paragraph; there may be groups in
  484. ; certain cases.
  485. )
  486. "Definition alist of relevant regexes.
  487. Each entry consists of the symbol naming the regex and an
  488. argument list for `rst-re'.")
  489. (defvar rst-re-alist) ; Forward declare to use it in `rst-re'.
  490. ;; FIXME: Use `sregex' or `rx' instead of re-inventing the wheel.
  491. (rst-testcover-add-compose 'rst-re)
  492. (defun rst-re (&rest args)
  493. ;; testcover: ok.
  494. "Interpret ARGS as regular expressions and return a regex string.
  495. Each element of ARGS may be one of the following:
  496. A string which is inserted unchanged.
  497. A character which is resolved to a quoted regex.
  498. A symbol which is resolved to a string using `rst-re-alist-def'.
  499. A list with a keyword in the car. Each element of the cdr of such
  500. a list is recursively interpreted as ARGS. The results of this
  501. interpretation are concatenated according to the keyword.
  502. For the keyword `:seq' the results are simply concatenated.
  503. For the keyword `:shy' the results are concatenated and
  504. surrounded by a shy-group (\"\\(?:...\\)\").
  505. For the keyword `:alt' the results form an alternative (\"\\|\")
  506. which is shy-grouped (\"\\(?:...\\)\").
  507. For the keyword `:grp' the results are concatenated and form a
  508. referenceable group (\"\\(...\\)\").
  509. After interpretation of ARGS the results are concatenated as for
  510. `:seq'."
  511. (apply #'concat
  512. (mapcar
  513. #'(lambda (re)
  514. (cond
  515. ((stringp re)
  516. re)
  517. ((symbolp re)
  518. (cadr (assoc re rst-re-alist)))
  519. ((characterp re)
  520. (regexp-quote (char-to-string re)))
  521. ((listp re)
  522. (let ((nested
  523. (mapcar (lambda (elt)
  524. (rst-re elt))
  525. (cdr re))))
  526. (cond
  527. ((eq (car re) :seq)
  528. (mapconcat #'identity nested ""))
  529. ((eq (car re) :shy)
  530. (concat "\\(?:" (mapconcat #'identity nested "") "\\)"))
  531. ((eq (car re) :grp)
  532. (concat "\\(" (mapconcat #'identity nested "") "\\)"))
  533. ((eq (car re) :alt)
  534. (concat "\\(?:" (mapconcat #'identity nested "\\|") "\\)"))
  535. (t
  536. (error "Unknown list car: %s" (car re))))))
  537. (t
  538. (error "Unknown object type for building regex: %s" re))))
  539. args)))
  540. ;; FIXME: Remove circular dependency between `rst-re' and `rst-re-alist'.
  541. (with-no-warnings ; Silence byte-compiler about this construction.
  542. (defconst rst-re-alist
  543. ;; Shadow global value we are just defining so we can construct it step by
  544. ;; step.
  545. (let (rst-re-alist)
  546. (dolist (re rst-re-alist-def rst-re-alist)
  547. (setq rst-re-alist
  548. (nconc rst-re-alist
  549. (list (list (car re) (apply #'rst-re (cdr re))))))))
  550. "Alist mapping symbols from `rst-re-alist-def' to regex strings."))
  551. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  552. ;; Concepts
  553. ;; Each of the following classes represents an own concept. The suffix of the
  554. ;; class name is used in the code to represent entities of the respective
  555. ;; class.
  556. ;;
  557. ;; In addition a reStructuredText section header in the buffer is called
  558. ;; "section".
  559. ;;
  560. ;; For lists a "s" is added to the name of the concepts.
  561. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  562. ;; Class rst-Ado
  563. (cl-defstruct
  564. (rst-Ado
  565. (:constructor nil) ; Prevent creating unchecked values.
  566. ;; Construct a transition.
  567. (:constructor
  568. rst-Ado-new-transition
  569. (&aux
  570. (char nil)
  571. (-style 'transition)))
  572. ;; Construct a simple section header.
  573. (:constructor
  574. rst-Ado-new-simple
  575. (char-arg
  576. &aux
  577. (char (rst-Ado--validate-char char-arg))
  578. (-style 'simple)))
  579. ;; Construct a over-and-under section header.
  580. (:constructor
  581. rst-Ado-new-over-and-under
  582. (char-arg
  583. &aux
  584. (char (rst-Ado--validate-char char-arg))
  585. (-style 'over-and-under)))
  586. ;; Construct from adornment with inverted style.
  587. (:constructor
  588. rst-Ado-new-invert
  589. (ado-arg
  590. &aux
  591. (char (rst-Ado-char ado-arg))
  592. (-style (let ((sty (rst-Ado--style ado-arg)))
  593. (cond
  594. ((eq sty 'simple)
  595. 'over-and-under)
  596. ((eq sty 'over-and-under)
  597. 'simple)
  598. (sty)))))))
  599. "Representation of a reStructuredText adornment.
  600. Adornments are either section markers where they markup the
  601. section header or transitions.
  602. This type is immutable."
  603. ;; The character used for the adornment.
  604. (char nil :read-only t)
  605. ;; The style of the adornment. This is a private attribute.
  606. (-style nil :read-only t))
  607. ;; Private class methods
  608. (defun rst-Ado--validate-char (char)
  609. ;; testcover: ok.
  610. "Validate CHAR to be a valid adornment character.
  611. Return CHAR if so or signal an error otherwise."
  612. (cl-check-type char character)
  613. (cl-check-type char (satisfies
  614. (lambda (c)
  615. (memq c rst-adornment-chars)))
  616. "Character must be a valid adornment character")
  617. char)
  618. ;; Public methods
  619. (defun rst-Ado-is-transition (self)
  620. ;; testcover: ok.
  621. "Return non-nil if SELF is a transition adornment."
  622. (cl-check-type self rst-Ado)
  623. (eq (rst-Ado--style self) 'transition))
  624. (defun rst-Ado-is-section (self)
  625. ;; testcover: ok.
  626. "Return non-nil if SELF is a section adornment."
  627. (cl-check-type self rst-Ado)
  628. (not (rst-Ado-is-transition self)))
  629. (defun rst-Ado-is-simple (self)
  630. ;; testcover: ok.
  631. "Return non-nil if SELF is a simple section adornment."
  632. (cl-check-type self rst-Ado)
  633. (eq (rst-Ado--style self) 'simple))
  634. (defun rst-Ado-is-over-and-under (self)
  635. ;; testcover: ok.
  636. "Return non-nil if SELF is a over-and-under section adornment."
  637. (cl-check-type self rst-Ado)
  638. (eq (rst-Ado--style self) 'over-and-under))
  639. (defun rst-Ado-equal (self other)
  640. ;; testcover: ok.
  641. "Return non-nil when SELF and OTHER are equal."
  642. (cl-check-type self rst-Ado)
  643. (cl-check-type other rst-Ado)
  644. (cond
  645. ((not (eq (rst-Ado--style self) (rst-Ado--style other)))
  646. nil)
  647. ((rst-Ado-is-transition self))
  648. ((equal (rst-Ado-char self) (rst-Ado-char other)))))
  649. (defun rst-Ado-position (self ados)
  650. ;; testcover: ok.
  651. "Return position of SELF in ADOS or nil."
  652. (cl-check-type self rst-Ado)
  653. (cl-position-if #'(lambda (e)
  654. (rst-Ado-equal self e))
  655. ados))
  656. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  657. ;; Class rst-Hdr
  658. (cl-defstruct
  659. (rst-Hdr
  660. (:constructor nil) ; Prevent creating unchecked values.
  661. ;; Construct while all parameters must be valid.
  662. (:constructor
  663. rst-Hdr-new
  664. (ado-arg
  665. indent-arg
  666. &aux
  667. (ado (rst-Hdr--validate-ado ado-arg))
  668. (indent (rst-Hdr--validate-indent indent-arg ado nil))))
  669. ;; Construct while all parameters but `indent' must be valid.
  670. (:constructor
  671. rst-Hdr-new-lax
  672. (ado-arg
  673. indent-arg
  674. &aux
  675. (ado (rst-Hdr--validate-ado ado-arg))
  676. (indent (rst-Hdr--validate-indent indent-arg ado t))))
  677. ;; Construct a header with same characteristics but opposite style as `ado'.
  678. (:constructor
  679. rst-Hdr-new-invert
  680. (ado-arg
  681. indent-arg
  682. &aux
  683. (ado (rst-Hdr--validate-ado (rst-Ado-new-invert ado-arg)))
  684. (indent (rst-Hdr--validate-indent indent-arg ado t))))
  685. (:copier nil)) ; Not really needed for an immutable type.
  686. "Representation of reStructuredText section header characteristics.
  687. This type is immutable."
  688. ;; The adornment of the header.
  689. (ado nil :read-only t)
  690. ;; The indentation of a title text or nil if not given.
  691. (indent nil :read-only t))
  692. ;; Private class methods
  693. (defun rst-Hdr--validate-indent (indent ado lax)
  694. ;; testcover: ok.
  695. "Validate INDENT to be a valid indentation for ADO.
  696. Return INDENT if so or signal an error otherwise. If LAX don't
  697. signal an error and return a valid indent."
  698. (cl-check-type indent integer)
  699. (cond
  700. ((zerop indent)
  701. indent)
  702. ((rst-Ado-is-simple ado)
  703. (if lax
  704. 0
  705. (signal 'args-out-of-range
  706. '("Indentation must be 0 for style simple"))))
  707. ((< indent 0)
  708. (if lax
  709. 0
  710. (signal 'args-out-of-range
  711. '("Indentation must not be negative"))))
  712. ;; Implicitly over-and-under.
  713. (indent)))
  714. (defun rst-Hdr--validate-ado (ado)
  715. ;; testcover: ok.
  716. "Validate ADO to be a valid adornment.
  717. Return ADO if so or signal an error otherwise."
  718. (cl-check-type ado rst-Ado)
  719. (cond
  720. ((rst-Ado-is-transition ado)
  721. (signal 'args-out-of-range
  722. '("Adornment for header must not be transition.")))
  723. (ado)))
  724. ;; Public class methods
  725. (defvar rst-preferred-adornments) ; Forward declaration.
  726. (defun rst-Hdr-preferred-adornments ()
  727. ;; testcover: ok.
  728. "Return preferred adornments as list of `rst-Hdr'."
  729. (mapcar (cl-function
  730. (lambda ((character style indent))
  731. (rst-Hdr-new-lax
  732. (if (eq style 'over-and-under)
  733. (rst-Ado-new-over-and-under character)
  734. (rst-Ado-new-simple character))
  735. indent)))
  736. rst-preferred-adornments))
  737. ;; Public methods
  738. (defun rst-Hdr-member-ado (self hdrs)
  739. ;; testcover: ok.
  740. "Return sublist of HDRS whose car's adornment equals that of SELF or nil."
  741. (cl-check-type self rst-Hdr)
  742. (let ((ado (rst-Hdr-ado self)))
  743. (cl-member-if #'(lambda (hdr)
  744. (rst-Ado-equal ado (rst-Hdr-ado hdr)))
  745. hdrs)))
  746. (defun rst-Hdr-ado-map (selves)
  747. ;; testcover: ok.
  748. "Return `rst-Ado' list extracted from elements of SELVES."
  749. (mapcar #'rst-Hdr-ado selves))
  750. (defun rst-Hdr-get-char (self)
  751. ;; testcover: ok.
  752. "Return character of the adornment of SELF."
  753. (cl-check-type self rst-Hdr)
  754. (rst-Ado-char (rst-Hdr-ado self)))
  755. (defun rst-Hdr-is-over-and-under (self)
  756. ;; testcover: ok.
  757. "Return non-nil if SELF is a over-and-under section header."
  758. (cl-check-type self rst-Hdr)
  759. (rst-Ado-is-over-and-under (rst-Hdr-ado self)))
  760. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  761. ;; Class rst-Ttl
  762. (cl-defstruct
  763. (rst-Ttl
  764. (:constructor nil) ; Prevent creating unchecked values.
  765. ;; Construct with valid parameters for all attributes.
  766. (:constructor ; Private constructor
  767. rst-Ttl--new
  768. (ado-arg
  769. match-arg
  770. indent-arg
  771. text-arg
  772. &aux
  773. (ado (rst-Ttl--validate-ado ado-arg))
  774. (match (rst-Ttl--validate-match match-arg ado))
  775. (indent (rst-Ttl--validate-indent indent-arg ado))
  776. (text (rst-Ttl--validate-text text-arg ado))
  777. (hdr (condition-case nil
  778. (rst-Hdr-new ado indent)
  779. (error nil)))))
  780. (:copier nil)) ; Not really needed for an immutable type.
  781. "Representation of a reStructuredText section header as found in a buffer.
  782. This type gathers information about an adorned part in the buffer.
  783. This type is immutable."
  784. ;; The adornment characteristics or nil for a title candidate.
  785. (ado nil :read-only t)
  786. ;; The match-data for `ado' in a form similarly returned by `match-data' (but
  787. ;; not necessarily with markers in buffers). Match group 0 matches the whole
  788. ;; construct. Match group 1 matches the overline adornment if present.
  789. ;; Match group 2 matches the section title text or the transition. Match
  790. ;; group 3 matches the underline adornment.
  791. (match nil :read-only t)
  792. ;; An indentation found for the title line or nil for a transition.
  793. (indent nil :read-only t)
  794. ;; The text of the title or nil for a transition.
  795. (text nil :read-only t)
  796. ;; The header characteristics if it is a valid section header.
  797. (hdr nil :read-only t)
  798. ;; FIXME refactoring: Should have an attribute `buffer' for the buffer this
  799. ;; title is found in. This breaks lots and lots of tests.
  800. ;; However, with private constructor they may not be
  801. ;; necessary any more. In case it is really a buffer then
  802. ;; also `match' could be real data from `match-data' which
  803. ;; contains markers instead of integers.
  804. )
  805. ;; Private class methods
  806. (defun rst-Ttl--validate-ado (ado)
  807. ;; testcover: ok.
  808. "Return valid ADO or signal error."
  809. (cl-check-type ado (or null rst-Ado))
  810. ado)
  811. (defun rst-Ttl--validate-match (match ado)
  812. ;; testcover: ok.
  813. "Return valid MATCH matching ADO or signal error."
  814. (cl-check-type ado (or null rst-Ado))
  815. (cl-check-type match list)
  816. (cl-check-type match (satisfies (lambda (m)
  817. (equal (length m) 8)))
  818. "Match data must consist of exactly 8 buffer positions.")
  819. (dolist (pos match)
  820. (cl-check-type pos (or null integer-or-marker)))
  821. (cl-destructuring-bind (all-beg all-end
  822. ovr-beg ovr-end
  823. txt-beg txt-end
  824. und-beg und-end) match
  825. (unless (and (integer-or-marker-p all-beg) (integer-or-marker-p all-end))
  826. (signal 'args-out-of-range
  827. '("First two elements of match data must be buffer positions.")))
  828. (cond
  829. ((null ado)
  830. (unless (and (null ovr-beg) (null ovr-end)
  831. (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
  832. (null und-beg) (null und-end))
  833. (signal 'args-out-of-range
  834. '("For a title candidate exactly the third match pair must be set."))))
  835. ((rst-Ado-is-transition ado)
  836. (unless (and (null ovr-beg) (null ovr-end)
  837. (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
  838. (null und-beg) (null und-end))
  839. (signal 'args-out-of-range
  840. '("For a transition exactly the third match pair must be set."))))
  841. ((rst-Ado-is-simple ado)
  842. (unless (and (null ovr-beg) (null ovr-end)
  843. (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
  844. (integer-or-marker-p und-beg) (integer-or-marker-p und-end))
  845. (signal 'args-out-of-range
  846. '("For a simple section adornment exactly the third and fourth match pair must be set."))))
  847. (t ; over-and-under
  848. (unless (and (integer-or-marker-p ovr-beg) (integer-or-marker-p ovr-end)
  849. (integer-or-marker-p txt-beg) (integer-or-marker-p txt-end)
  850. (or (null und-beg) (integer-or-marker-p und-beg))
  851. (or (null und-end) (integer-or-marker-p und-end)))
  852. (signal 'args-out-of-range
  853. '("For a over-and-under section adornment all match pairs must be set."))))))
  854. match)
  855. (defun rst-Ttl--validate-indent (indent ado)
  856. ;; testcover: ok.
  857. "Return valid INDENT for ADO or signal error."
  858. (if (and ado (rst-Ado-is-transition ado))
  859. (cl-check-type indent null
  860. "Indent for a transition must be nil.")
  861. (cl-check-type indent (integer 0 *)
  862. "Indent for a section header must be non-negative."))
  863. indent)
  864. (defun rst-Ttl--validate-text (text ado)
  865. ;; testcover: ok.
  866. "Return valid TEXT for ADO or signal error."
  867. (if (and ado (rst-Ado-is-transition ado))
  868. (cl-check-type text null
  869. "Transitions may not have title text.")
  870. (cl-check-type text string))
  871. text)
  872. ;; Public class methods
  873. (defun rst-Ttl-from-buffer (ado beg-ovr beg-txt beg-und txt)
  874. ;; testcover: ok.
  875. "Return a `rst-Ttl' constructed from information in the current buffer.
  876. ADO is the adornment or nil for a title candidate. BEG-OVR and
  877. BEG-UND are the starting points of the overline or underline,
  878. respectively. They may be nil if the respective thing is missing.
  879. BEG-TXT is the beginning of the title line or the transition and
  880. must be given. The end of the line is used as the end point. TXT
  881. is the title text or nil. If TXT is given the indentation of the
  882. line containing BEG-TXT is used as indentation. Match group 0 is
  883. derived from the remaining information."
  884. (cl-check-type beg-txt integer-or-marker)
  885. (save-excursion
  886. (let ((end-ovr (when beg-ovr
  887. (goto-char beg-ovr)
  888. (line-end-position)))
  889. (end-txt (progn
  890. (goto-char beg-txt)
  891. (line-end-position)))
  892. (end-und (when beg-und
  893. (goto-char beg-und)
  894. (line-end-position)))
  895. (ind (when txt
  896. (goto-char beg-txt)
  897. (current-indentation))))
  898. (rst-Ttl--new ado
  899. (list
  900. (or beg-ovr beg-txt) (or end-und end-txt)
  901. beg-ovr end-ovr
  902. beg-txt end-txt
  903. beg-und end-und)
  904. ind txt))))
  905. ;; Public methods
  906. (defun rst-Ttl-get-title-beginning (self)
  907. ;; testcover: ok.
  908. "Return position of beginning of title text of SELF.
  909. This position should always be at the start of a line."
  910. (cl-check-type self rst-Ttl)
  911. (nth 4 (rst-Ttl-match self)))
  912. (defun rst-Ttl-get-beginning (self)
  913. ;; testcover: ok.
  914. "Return position of beginning of whole SELF."
  915. (cl-check-type self rst-Ttl)
  916. (nth 0 (rst-Ttl-match self)))
  917. (defun rst-Ttl-get-end (self)
  918. ;; testcover: ok.
  919. "Return position of end of whole SELF."
  920. (cl-check-type self rst-Ttl)
  921. (nth 1 (rst-Ttl-match self)))
  922. (defun rst-Ttl-is-section (self)
  923. ;; testcover: ok.
  924. "Return non-nil if SELF is a section header or candidate."
  925. (cl-check-type self rst-Ttl)
  926. (rst-Ttl-text self))
  927. (defun rst-Ttl-is-candidate (self)
  928. ;; testcover: ok.
  929. "Return non-nil if SELF is a candidate for a section header."
  930. (cl-check-type self rst-Ttl)
  931. (not (rst-Ttl-ado self)))
  932. (defun rst-Ttl-contains (self position)
  933. "Return whether SELF contain POSITION.
  934. Return 0 if SELF contains POSITION, < 0 if SELF ends before
  935. POSITION and > 0 if SELF starts after position."
  936. (cl-check-type self rst-Ttl)
  937. (cl-check-type position integer-or-marker)
  938. (cond
  939. ((< (nth 1 (rst-Ttl-match self)) position)
  940. -1)
  941. ((> (nth 0 (rst-Ttl-match self)) position)
  942. +1)
  943. (0)))
  944. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  945. ;; Class rst-Stn
  946. (cl-defstruct
  947. (rst-Stn
  948. (:constructor nil) ; Prevent creating unchecked values.
  949. ;; Construct while all parameters must be valid.
  950. (:constructor
  951. rst-Stn-new
  952. (ttl-arg
  953. level-arg
  954. children-arg
  955. &aux
  956. (ttl (rst-Stn--validate-ttl ttl-arg))
  957. (level (rst-Stn--validate-level level-arg ttl))
  958. (children (rst-Stn--validate-children children-arg ttl)))))
  959. "Representation of a section tree node.
  960. This type is immutable."
  961. ;; The title of the node or nil for a missing node.
  962. (ttl nil :read-only t)
  963. ;; The level of the node in the tree. Negative for the (virtual) top level
  964. ;; node.
  965. (level nil :read-only t)
  966. ;; The list of children of the node.
  967. (children nil :read-only t))
  968. ;; FIXME refactoring: Should have an attribute `buffer' for the buffer this
  969. ;; title is found in. Or use `rst-Ttl-buffer'.
  970. ;; Private class methods
  971. (defun rst-Stn--validate-ttl (ttl)
  972. ;; testcover: ok.
  973. "Return valid TTL or signal error."
  974. (cl-check-type ttl (or null rst-Ttl))
  975. ttl)
  976. (defun rst-Stn--validate-level (level ttl)
  977. ;; testcover: ok.
  978. "Return valid LEVEL for TTL or signal error."
  979. (cl-check-type level integer)
  980. (when (and ttl (< level 0))
  981. ;; testcover: Never reached because a title may not have a negative level
  982. (signal 'args-out-of-range
  983. '("Top level node must not have a title.")))
  984. level)
  985. (defun rst-Stn--validate-children (children ttl)
  986. ;; testcover: ok.
  987. "Return valid CHILDREN for TTL or signal error."
  988. (cl-check-type children list)
  989. (dolist (child children)
  990. (cl-check-type child rst-Stn))
  991. (unless (or ttl children)
  992. (signal 'args-out-of-range
  993. '("A missing node must have children.")))
  994. children)
  995. ;; Public methods
  996. (defun rst-Stn-get-title-beginning (self)
  997. ;; testcover: ok.
  998. "Return the beginning of the title of SELF.
  999. Handles missing node properly."
  1000. (cl-check-type self rst-Stn)
  1001. (let ((ttl (rst-Stn-ttl self)))
  1002. (if ttl
  1003. (rst-Ttl-get-title-beginning ttl)
  1004. (rst-Stn-get-title-beginning (car (rst-Stn-children self))))))
  1005. (defun rst-Stn-get-text (self &optional default)
  1006. ;; testcover: ok.
  1007. "Return title text of SELF or DEFAULT if SELF is a missing node.
  1008. For a missing node and no DEFAULT given return a standard title text."
  1009. (cl-check-type self rst-Stn)
  1010. (let ((ttl (rst-Stn-ttl self)))
  1011. (cond
  1012. (ttl
  1013. (rst-Ttl-text ttl))
  1014. (default)
  1015. ("[missing node]"))))
  1016. (defun rst-Stn-is-top (self)
  1017. ;; testcover: ok.
  1018. "Return non-nil if SELF is a top level node."
  1019. (cl-check-type self rst-Stn)
  1020. (< (rst-Stn-level self) 0))
  1021. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1022. ;; Mode definition
  1023. (defun rst-define-key (keymap key def &rest deprecated)
  1024. ;; testcover: ok.
  1025. "Bind like `define-key' but add deprecated key definitions.
  1026. KEYMAP, KEY, and DEF are as in `define-key'. DEPRECATED key
  1027. definitions should be in vector notation. These are defined
  1028. as well but give an additional message."
  1029. (define-key keymap key def)
  1030. (when deprecated
  1031. (let* ((command-name (symbol-name def))
  1032. (forwarder-function-name
  1033. (if (string-match "^rst-\\(.*\\)$" command-name)
  1034. (concat "rst-deprecated-"
  1035. (match-string 1 command-name))
  1036. (error "Not an RST command: %s" command-name)))
  1037. (forwarder-function (intern forwarder-function-name)))
  1038. (unless (fboundp forwarder-function)
  1039. (defalias forwarder-function
  1040. (lambda ()
  1041. (interactive)
  1042. (call-interactively def)
  1043. (message "[Deprecated use of key %s; use key %s instead]"
  1044. (key-description (this-command-keys))
  1045. (key-description key)))
  1046. ;; FIXME: In Emacs-25 we could use (:documentation ...) instead.
  1047. (format "Deprecated binding for %s, use \\[%s] instead."
  1048. def def)))
  1049. (dolist (dep-key deprecated)
  1050. (define-key keymap dep-key forwarder-function)))))
  1051. ;; Key bindings.
  1052. (defvar rst-mode-map
  1053. (let ((map (make-sparse-keymap)))
  1054. ;; \C-c is the general keymap.
  1055. (rst-define-key map [?\C-c ?\C-h] #'describe-prefix-bindings)
  1056. ;;
  1057. ;; Section Adornments
  1058. ;;
  1059. ;; The adjustment function that adorns or rotates a section title.
  1060. (rst-define-key map [?\C-c ?\C-=] #'rst-adjust [?\C-c ?\C-a t])
  1061. (rst-define-key map [?\C-=] #'rst-adjust) ; Does not work on macOS and
  1062. ; on consoles.
  1063. ;; \C-c \C-a is the keymap for adornments.
  1064. (rst-define-key map [?\C-c ?\C-a ?\C-h] #'describe-prefix-bindings)
  1065. ;; Another binding which works with all types of input.
  1066. (rst-define-key map [?\C-c ?\C-a ?\C-a] #'rst-adjust)
  1067. ;; Display the hierarchy of adornments implied by the current document
  1068. ;; contents.
  1069. (rst-define-key map [?\C-c ?\C-a ?\C-d] #'rst-display-hdr-hierarchy)
  1070. ;; Homogenize the adornments in the document.
  1071. (rst-define-key map [?\C-c ?\C-a ?\C-s] #'rst-straighten-sections
  1072. [?\C-c ?\C-s])
  1073. ;;
  1074. ;; Section Movement and Selection
  1075. ;;
  1076. ;; Mark the subsection where the cursor is.
  1077. (rst-define-key map [?\C-\M-h] #'rst-mark-section
  1078. ;; Same as mark-defun sgml-mark-current-element.
  1079. [?\C-c ?\C-m])
  1080. ;; Move backward/forward between section titles.
  1081. ;; FIXME: Also bind similar to outline mode.
  1082. (rst-define-key map [?\C-\M-a] #'rst-backward-section
  1083. ;; Same as beginning-of-defun.
  1084. [?\C-c ?\C-n])
  1085. (rst-define-key map [?\C-\M-e] #'rst-forward-section
  1086. ;; Same as end-of-defun.
  1087. [?\C-c ?\C-p])
  1088. ;;
  1089. ;; Operating on regions
  1090. ;;
  1091. ;; \C-c \C-r is the keymap for regions.
  1092. (rst-define-key map [?\C-c ?\C-r ?\C-h] #'describe-prefix-bindings)
  1093. ;; Makes region a line-block.
  1094. (rst-define-key map [?\C-c ?\C-r ?\C-l] #'rst-line-block-region
  1095. [?\C-c ?\C-d])
  1096. ;; Shift region left or right according to tabs.
  1097. (rst-define-key map [?\C-c ?\C-r tab] #'rst-shift-region
  1098. [?\C-c ?\C-r t] [?\C-c ?\C-l t])
  1099. ;;
  1100. ;; Operating on lists
  1101. ;;
  1102. ;; \C-c \C-l is the keymap for lists.
  1103. (rst-define-key map [?\C-c ?\C-l ?\C-h] #'describe-prefix-bindings)
  1104. ;; Makes paragraphs in region as a bullet list.
  1105. (rst-define-key map [?\C-c ?\C-l ?\C-b] #'rst-bullet-list-region
  1106. [?\C-c ?\C-b])
  1107. ;; Makes paragraphs in region as a enumeration.
  1108. (rst-define-key map [?\C-c ?\C-l ?\C-e] #'rst-enumerate-region
  1109. [?\C-c ?\C-e])
  1110. ;; Converts bullets to an enumeration.
  1111. (rst-define-key map [?\C-c ?\C-l ?\C-c] #'rst-convert-bullets-to-enumeration
  1112. [?\C-c ?\C-v])
  1113. ;; Make sure that all the bullets in the region are consistent.
  1114. (rst-define-key map [?\C-c ?\C-l ?\C-s] #'rst-straighten-bullets-region
  1115. [?\C-c ?\C-w])
  1116. ;; Insert a list item.
  1117. (rst-define-key map [?\C-c ?\C-l ?\C-i] #'rst-insert-list)
  1118. ;;
  1119. ;; Table-of-Contents Features
  1120. ;;
  1121. ;; \C-c \C-t is the keymap for table of contents.
  1122. (rst-define-key map [?\C-c ?\C-t ?\C-h] #'describe-prefix-bindings)
  1123. ;; Enter a TOC buffer to view and move to a specific section.
  1124. (rst-define-key map [?\C-c ?\C-t ?\C-t] #'rst-toc)
  1125. ;; Insert a TOC here.
  1126. (rst-define-key map [?\C-c ?\C-t ?\C-i] #'rst-toc-insert
  1127. [?\C-c ?\C-i])
  1128. ;; Update the document's TOC (without changing the cursor position).
  1129. (rst-define-key map [?\C-c ?\C-t ?\C-u] #'rst-toc-update
  1130. [?\C-c ?\C-u])
  1131. ;; Go to the section under the cursor (cursor must be in internal TOC).
  1132. (rst-define-key map [?\C-c ?\C-t ?\C-j] #'rst-toc-follow-link
  1133. [?\C-c ?\C-f])
  1134. ;;
  1135. ;; Converting Documents from Emacs
  1136. ;;
  1137. ;; \C-c \C-c is the keymap for compilation.
  1138. (rst-define-key map [?\C-c ?\C-c ?\C-h] #'describe-prefix-bindings)
  1139. ;; Run one of two pre-configured toolset commands on the document.
  1140. (rst-define-key map [?\C-c ?\C-c ?\C-c] #'rst-compile
  1141. [?\C-c ?1])
  1142. (rst-define-key map [?\C-c ?\C-c ?\C-a] #'rst-compile-alt-toolset
  1143. [?\C-c ?2])
  1144. ;; Convert the active region to pseudo-xml using the docutils tools.
  1145. (rst-define-key map [?\C-c ?\C-c ?\C-x] #'rst-compile-pseudo-region
  1146. [?\C-c ?3])
  1147. ;; Convert the current document to PDF and launch a viewer on the results.
  1148. (rst-define-key map [?\C-c ?\C-c ?\C-p] #'rst-compile-pdf-preview
  1149. [?\C-c ?4])
  1150. ;; Convert the current document to S5 slides and view in a web browser.
  1151. (rst-define-key map [?\C-c ?\C-c ?\C-s] #'rst-compile-slides-preview
  1152. [?\C-c ?5])
  1153. map)
  1154. "Keymap for reStructuredText mode commands.
  1155. This inherits from Text mode.")
  1156. ;; Abbrevs.
  1157. (define-abbrev-table 'rst-mode-abbrev-table
  1158. (mapcar #'(lambda (x)
  1159. (append x '(nil 0 system)))
  1160. '(("contents" ".. contents::\n..\n ")
  1161. ("con" ".. contents::\n..\n ")
  1162. ("cont" "[...]")
  1163. ("skip" "\n\n[...]\n\n ")
  1164. ("seq" "\n\n[...]\n\n ")
  1165. ;; FIXME: Add footnotes, links, and more.
  1166. ))
  1167. "Abbrev table used while in `rst-mode'.")
  1168. ;; Syntax table.
  1169. (defvar rst-mode-syntax-table
  1170. (let ((st (copy-syntax-table text-mode-syntax-table)))
  1171. (modify-syntax-entry ?$ "." st)
  1172. (modify-syntax-entry ?% "." st)
  1173. (modify-syntax-entry ?& "." st)
  1174. (modify-syntax-entry ?' "." st)
  1175. (modify-syntax-entry ?* "." st)
  1176. (modify-syntax-entry ?+ "." st)
  1177. (modify-syntax-entry ?- "." st)
  1178. (modify-syntax-entry ?/ "." st)
  1179. (modify-syntax-entry ?< "." st)
  1180. (modify-syntax-entry ?= "." st)
  1181. (modify-syntax-entry ?> "." st)
  1182. (modify-syntax-entry ?\\ "\\" st)
  1183. (modify-syntax-entry ?_ "." st)
  1184. (modify-syntax-entry ?| "." st)
  1185. (modify-syntax-entry ?« "." st)
  1186. (modify-syntax-entry ?» "." st)
  1187. (modify-syntax-entry ?‘ "." st)
  1188. (modify-syntax-entry ?’ "." st)
  1189. (modify-syntax-entry ?“ "." st)
  1190. (modify-syntax-entry ?” "." st)
  1191. st)
  1192. "Syntax table used while in `rst-mode'.")
  1193. (defcustom rst-mode-hook nil
  1194. "Hook run when `rst-mode' is turned on.
  1195. The hook for `text-mode' is run before this one."
  1196. :group 'rst
  1197. :type '(hook))
  1198. (rst-testcover-defcustom)
  1199. ;; Pull in variable definitions silencing byte-compiler.
  1200. (require 'newcomment)
  1201. (defvar electric-pair-pairs)
  1202. (defvar electric-indent-inhibit)
  1203. ;; Use rst-mode for *.rst and *.rest files. Many ReStructured-Text files
  1204. ;; use *.txt, but this is too generic to be set as a default.
  1205. ;;;###autoload (add-to-list 'auto-mode-alist (purecopy '("\\.re?st\\'" . rst-mode)))
  1206. ;;;###autoload
  1207. (define-derived-mode rst-mode text-mode "ReST"
  1208. "Major mode for editing reStructuredText documents.
  1209. \\<rst-mode-map>
  1210. Turning on `rst-mode' calls the normal hooks `text-mode-hook'
  1211. and `rst-mode-hook'. This mode also supports font-lock
  1212. highlighting.
  1213. \\{rst-mode-map}"
  1214. :abbrev-table rst-mode-abbrev-table
  1215. :syntax-table rst-mode-syntax-table
  1216. :group 'rst
  1217. ;; Paragraph recognition.
  1218. (setq-local paragraph-separate
  1219. (rst-re '(:alt
  1220. "\f"
  1221. lin-end)))
  1222. (setq-local paragraph-start
  1223. (rst-re '(:alt
  1224. "\f"
  1225. lin-end
  1226. (:seq hws-tag par-tag- bli-sfx))))
  1227. ;; Indenting and filling.
  1228. (setq-local indent-line-function #'rst-indent-line)
  1229. (setq-local adaptive-fill-mode t)
  1230. (setq-local adaptive-fill-regexp (rst-re 'hws-tag 'par-tag- "?" 'hws-tag))
  1231. (setq-local adaptive-fill-function #'rst-adaptive-fill)
  1232. (setq-local fill-paragraph-handle-comment nil)
  1233. ;; Comments.
  1234. (setq-local comment-start ".. ")
  1235. (setq-local comment-start-skip (rst-re 'lin-beg 'exm-tag 'bli-sfx))
  1236. (setq-local comment-continue " ")
  1237. (setq-local comment-multi-line t)
  1238. (setq-local comment-use-syntax nil)
  1239. ;; reStructuredText has not really a comment ender but nil is not really a
  1240. ;; permissible value.
  1241. (setq-local comment-end "")
  1242. (setq-local comment-end-skip nil)
  1243. ;; Commenting in reStructuredText is very special so use our own set of
  1244. ;; functions.
  1245. (setq-local comment-line-break-function #'rst-comment-line-break)
  1246. (setq-local comment-indent-function #'rst-comment-indent)
  1247. (setq-local comment-insert-comment-function #'rst-comment-insert-comment)
  1248. (setq-local comment-region-function #'rst-comment-region)
  1249. (setq-local uncomment-region-function #'rst-uncomment-region)
  1250. (setq-local electric-pair-pairs '((?\" . ?\") (?\* . ?\*) (?\` . ?\`)))
  1251. ;; Imenu and which function.
  1252. ;; FIXME: Check documentation of `which-function' for alternative ways to
  1253. ;; determine the current function name.
  1254. (setq-local imenu-create-index-function #'rst-imenu-create-index)
  1255. ;; Font lock.
  1256. (setq-local font-lock-defaults
  1257. '(rst-font-lock-keywords
  1258. t nil nil nil
  1259. (font-lock-multiline . t)
  1260. (font-lock-mark-block-function . mark-paragraph)))
  1261. (add-hook 'font-lock-extend-region-functions #'rst-font-lock-extend-region t)
  1262. ;; Text after a changed line may need new fontification.
  1263. (setq-local jit-lock-contextually t)
  1264. ;; Indentation is not deterministic.
  1265. (setq-local electric-indent-inhibit t))
  1266. ;;;###autoload
  1267. (define-minor-mode rst-minor-mode
  1268. "Toggle ReST minor mode.
  1269. With a prefix argument ARG, enable ReST minor mode if ARG is
  1270. positive, and disable it otherwise. If called from Lisp, enable
  1271. the mode if ARG is omitted or nil.
  1272. When ReST minor mode is enabled, the ReST mode keybindings
  1273. are installed on top of the major mode bindings. Use this
  1274. for modes derived from Text mode, like Mail mode."
  1275. ;; The initial value.
  1276. nil
  1277. ;; The indicator for the mode line.
  1278. " ReST"
  1279. ;; The minor mode bindings.
  1280. rst-mode-map
  1281. :group 'rst)
  1282. ;; FIXME: can I somehow install these too?
  1283. ;; :abbrev-table rst-mode-abbrev-table
  1284. ;; :syntax-table rst-mode-syntax-table
  1285. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1286. ;; Section adornment adjustment
  1287. ;; The following functions implement a smart automatic title sectioning feature.
  1288. ;; The idea is that with the cursor sitting on a section title, we try to get as
  1289. ;; much information from context and try to do the best thing automatically.
  1290. ;; This function can be invoked many times and/or with prefix argument to rotate
  1291. ;; between the various sectioning adornments.
  1292. ;;
  1293. ;; Some notes:
  1294. ;;
  1295. ;; - The underlining character that is used depends on context. The file is
  1296. ;; scanned to find other sections and an appropriate character is selected.
  1297. ;; If the function is invoked on a section that is complete, the character is
  1298. ;; rotated among the existing section adornments.
  1299. ;;
  1300. ;; Note that when rotating the characters, if we come to the end of the
  1301. ;; hierarchy of adornments, the variable `rst-preferred-adornments' is
  1302. ;; consulted to propose a new underline adornment, and if continued, we cycle
  1303. ;; the adornments all over again. Set this variable to nil if you want to
  1304. ;; limit the underlining character propositions to the existing adornments in
  1305. ;; the file.
  1306. ;;
  1307. ;; - An underline/overline that is not extended to the column at which it should
  1308. ;; be hanging is dubbed INCOMPLETE. For example::
  1309. ;;
  1310. ;; |Some Title
  1311. ;; |-------
  1312. ;;
  1313. ;; Examples of default invocation:
  1314. ;;
  1315. ;; |Some Title ---> |Some Title
  1316. ;; | |----------
  1317. ;;
  1318. ;; |Some Title ---> |Some Title
  1319. ;; |----- |----------
  1320. ;;
  1321. ;; | |------------
  1322. ;; | Some Title ---> | Some Title
  1323. ;; | |------------
  1324. ;;
  1325. ;; In over-and-under style, when alternating the style, a variable is
  1326. ;; available to select how much default indent to use (it can be zero). Note
  1327. ;; that if the current section adornment already has an indent, we don't
  1328. ;; adjust it to the default, we rather use the current indent that is already
  1329. ;; there for adjustment (unless we cycle, in which case we use the indent
  1330. ;; that has been found previously).
  1331. (defgroup rst-adjust nil
  1332. "Settings for adjustment and cycling of section title adornments."
  1333. :group 'rst
  1334. :version "21.1")
  1335. (define-obsolete-variable-alias
  1336. 'rst-preferred-decorations 'rst-preferred-adornments "rst 1.0.0")
  1337. ;; FIXME: Default must match suggestion in
  1338. ;; http://sphinx-doc.org/rest.html#sections for Python documentation.
  1339. (defcustom rst-preferred-adornments '((?= over-and-under 1)
  1340. (?= simple 0)
  1341. (?- simple 0)
  1342. (?~ simple 0)
  1343. (?+ simple 0)
  1344. (?` simple 0)
  1345. (?# simple 0)
  1346. (?@ simple 0))
  1347. "Preferred hierarchy of section title adornments.
  1348. A list consisting of lists of the form (CHARACTER STYLE INDENT).
  1349. CHARACTER is the character used. STYLE is one of the symbols
  1350. `over-and-under' or `simple'. INDENT is an integer giving the
  1351. wanted indentation for STYLE `over-and-under'.
  1352. This sequence is consulted to offer a new adornment suggestion
  1353. when we rotate the underlines at the end of the existing
  1354. hierarchy of characters, or when there is no existing section
  1355. title in the file.
  1356. Set this to an empty list to use only the adornment found in the
  1357. file."
  1358. :group 'rst-adjust
  1359. :type `(repeat
  1360. (group :tag "Adornment specification"
  1361. (choice :tag "Adornment character"
  1362. ,@(mapcar #'(lambda (char)
  1363. (list 'const
  1364. :tag (char-to-string char) char))
  1365. rst-adornment-chars))
  1366. (radio :tag "Adornment type"
  1367. (const :tag "Overline and underline" over-and-under)
  1368. (const :tag "Underline only" simple))
  1369. (integer :tag "Indentation for overline and underline type"
  1370. :value 0))))
  1371. (rst-testcover-defcustom)
  1372. ;; FIXME: Rename this to `rst-over-and-under-default-indent' and set default to
  1373. ;; 0 because the effect of 1 is probably surprising in the few cases
  1374. ;; where this is used.
  1375. ;; FIXME: A matching adornment style can be looked for in
  1376. ;; `rst-preferred-adornments' and its indentation used before using this
  1377. ;; variable.
  1378. (defcustom rst-default-indent 1
  1379. "Number of characters to indent the section title.
  1380. This is only used while toggling adornment styles when switching
  1381. from a simple adornment style to a over-and-under adornment
  1382. style. In addition this is used in cases where the adornments
  1383. found in the buffer are to be used but the indentation for
  1384. over-and-under adornments is inconsistent across the buffer."
  1385. :group 'rst-adjust
  1386. :type '(integer))
  1387. (rst-testcover-defcustom)
  1388. (defun rst-new-preferred-hdr (seen prev)
  1389. ;; testcover: ok.
  1390. "Return a new, preferred `rst-Hdr' different from all in SEEN.
  1391. PREV is the previous `rst-Hdr' in the buffer. If given the
  1392. search starts after this entry. Return nil if no new preferred
  1393. `rst-Hdr' can be found."
  1394. ;; All preferred adornments are candidates.
  1395. (let ((candidates
  1396. (append
  1397. (if prev
  1398. ;; Start searching after the level of the previous adornment.
  1399. (cdr (rst-Hdr-member-ado prev (rst-Hdr-preferred-adornments))))
  1400. (rst-Hdr-preferred-adornments))))
  1401. (cl-find-if #'(lambda (cand)
  1402. (not (rst-Hdr-member-ado cand seen)))
  1403. candidates)))
  1404. (defun rst-update-section (hdr)
  1405. ;; testcover: ok.
  1406. "Unconditionally update the style of the section header at point to HDR.
  1407. If there are existing overline and/or underline from the
  1408. existing adornment, they are removed before adding the
  1409. requested adornment."
  1410. (end-of-line)
  1411. (let ((indent (or (rst-Hdr-indent hdr) 0))
  1412. (marker (point-marker))
  1413. new)
  1414. ;; Fixup whitespace at the beginning and end of the line.
  1415. (1value
  1416. (rst-forward-line-strict 0))
  1417. (delete-horizontal-space)
  1418. (insert (make-string indent ? ))
  1419. (end-of-line)
  1420. (delete-horizontal-space)
  1421. (setq new (make-string (+ (current-column) indent) (rst-Hdr-get-char hdr)))
  1422. ;; Remove previous line if it is an adornment.
  1423. ;; FIXME refactoring: Check whether this deletes `hdr' which *has* all the
  1424. ;; data necessary.
  1425. (when (and (rst-forward-line-looking-at -1 'ado-beg-2-1)
  1426. ;; Avoid removing the underline of a title right above us.
  1427. (not (rst-forward-line-looking-at -2 'ttl-beg-1)))
  1428. (rst-delete-entire-line -1))
  1429. ;; Remove following line if it is an adornment.
  1430. (when (rst-forward-line-looking-at +1 'ado-beg-2-1)
  1431. (rst-delete-entire-line +1))
  1432. ;; Insert underline.
  1433. (unless (rst-forward-line-strict +1)
  1434. ;; Normalize buffer by adding final newline.
  1435. (newline 1))
  1436. (open-line 1)
  1437. (insert new)
  1438. ;; Insert overline.
  1439. (when (rst-Hdr-is-over-and-under hdr)
  1440. (1value ; Underline inserted above.
  1441. (rst-forward-line-strict -1))
  1442. (open-line 1)
  1443. (insert new))
  1444. (goto-char marker)))
  1445. (defun rst-classify-adornment (adornment end &optional accept-over-only)
  1446. ;; testcover: ok.
  1447. "Classify adornment string for section titles and transitions.
  1448. ADORNMENT is the complete adornment string as found in the buffer
  1449. with optional trailing whitespace. END is the point after the
  1450. last character of ADORNMENT. Return a `rst-Ttl' or nil if no
  1451. syntactically valid adornment is found. If ACCEPT-OVER-ONLY an
  1452. overline with a missing underline is accepted as valid and
  1453. returned."
  1454. (save-excursion
  1455. (save-match-data
  1456. (when (string-match (rst-re 'ado-beg-2-1) adornment)
  1457. (goto-char end)
  1458. (let* ((ado-ch (string-to-char (match-string 2 adornment)))
  1459. (ado-re (rst-re ado-ch 'adorep3-hlp)) ; RE matching the
  1460. ; adornment.
  1461. (beg-pnt (progn
  1462. (1value
  1463. (rst-forward-line-strict 0))
  1464. (point)))
  1465. (nxt-emp ; Next line nonexistent or empty
  1466. (not (rst-forward-line-looking-at +1 'lin-end #'not)))
  1467. (prv-emp ; Previous line nonexistent or empty
  1468. (not (rst-forward-line-looking-at -1 'lin-end #'not)))
  1469. txt-blw
  1470. (ttl-blw ; Title found below starting here.
  1471. (rst-forward-line-looking-at
  1472. +1 'ttl-beg-1
  1473. #'(lambda (mtcd)
  1474. (when mtcd
  1475. (setq txt-blw (match-string-no-properties 1))
  1476. (point)))))
  1477. txt-abv
  1478. (ttl-abv ; Title found above starting here.
  1479. (rst-forward-line-looking-at
  1480. -1 'ttl-beg-1
  1481. #'(lambda (mtcd)
  1482. (when mtcd
  1483. (setq txt-abv (match-string-no-properties 1))
  1484. (point)))))
  1485. (und-fnd ; Matching underline found starting here.
  1486. (and ttl-blw
  1487. (rst-forward-line-looking-at
  1488. +2 (list ado-re 'lin-end)
  1489. #'(lambda (mtcd)
  1490. (when mtcd
  1491. (point))))))
  1492. (ovr-fnd ; Matching overline found starting here.
  1493. (and ttl-abv
  1494. (rst-forward-line-looking-at
  1495. -2 (list ado-re 'lin-end)
  1496. #'(lambda (mtcd)
  1497. (when mtcd
  1498. (point))))))
  1499. (und-wng ; Wrong underline found starting here.
  1500. (and ttl-blw
  1501. (not und-fnd)
  1502. (rst-forward-line-looking-at
  1503. +2 'ado-beg-2-1
  1504. #'(lambda (mtcd)
  1505. (when mtcd
  1506. (point))))))
  1507. (ovr-wng ; Wrong overline found starting here.
  1508. (and ttl-abv (not ovr-fnd)
  1509. (rst-forward-line-looking-at
  1510. -2 'ado-beg-2-1
  1511. #'(lambda (mtcd)
  1512. (when (and
  1513. mtcd
  1514. ;; An adornment above may be a legal
  1515. ;; adornment for the line above - consider it
  1516. ;; a wrong overline only when it is equally
  1517. ;; long.
  1518. (equal
  1519. (length (match-string-no-properties 1))
  1520. (length adornment)))
  1521. (point)))))))
  1522. (cond
  1523. ((and nxt-emp prv-emp)
  1524. ;; A transition.
  1525. (rst-Ttl-from-buffer (rst-Ado-new-transition)
  1526. nil beg-pnt nil nil))
  1527. (ovr-fnd ; Prefer overline match over underline match.
  1528. ;; An overline with an underline.
  1529. (rst-Ttl-from-buffer (rst-Ado-new-over-and-under ado-ch)
  1530. ovr-fnd ttl-abv beg-pnt txt-abv))
  1531. (und-fnd
  1532. ;; An overline with an underline.
  1533. (rst-Ttl-from-buffer (rst-Ado-new-over-and-under ado-ch)
  1534. beg-pnt ttl-blw und-fnd txt-blw))
  1535. ((and ttl-abv (not ovr-wng))
  1536. ;; An underline.
  1537. (rst-Ttl-from-buffer (rst-Ado-new-simple ado-ch)
  1538. nil ttl-abv beg-pnt txt-abv))
  1539. ((and accept-over-only ttl-blw (not und-wng))
  1540. ;; An overline with a missing underline.
  1541. (rst-Ttl-from-buffer (rst-Ado-new-over-and-under ado-ch)
  1542. beg-pnt ttl-blw nil txt-blw))
  1543. (t
  1544. ;; Invalid adornment.
  1545. nil)))))))
  1546. (defun rst-ttl-at-point ()
  1547. ;; testcover: ok.
  1548. "Find a section title line around point and return its characteristics.
  1549. If the point is on an adornment line find the respective title
  1550. line. If the point is on an empty line check previous or next
  1551. line whether it is a suitable title line and use it if so. If
  1552. point is on a suitable title line use it. Return a `rst-Ttl' for
  1553. a section header or nil if no title line is found."
  1554. (save-excursion
  1555. (save-match-data
  1556. (1value
  1557. (rst-forward-line-strict 0))
  1558. (let* (cnd-beg ; Beginning of a title candidate.
  1559. cnd-txt ; Text of a title candidate.
  1560. (cnd-fun #'(lambda (mtcd) ; Function setting title candidate data.
  1561. (when mtcd
  1562. (setq cnd-beg (match-beginning 0))
  1563. (setq cnd-txt (match-string-no-properties 1))
  1564. t)))
  1565. ttl)
  1566. (cond
  1567. ((looking-at (rst-re 'ado-beg-2-1))
  1568. ;; Adornment found - consider it.
  1569. (setq ttl (rst-classify-adornment (match-string-no-properties 0)
  1570. (match-end 0) t)))
  1571. ((looking-at (rst-re 'lin-end))
  1572. ;; Empty line found - check surrounding lines for a title.
  1573. (or
  1574. (rst-forward-line-looking-at -1 'ttl-beg-1 cnd-fun)
  1575. (rst-forward-line-looking-at +1 'ttl-beg-1 cnd-fun)))
  1576. ((looking-at (rst-re 'ttl-beg-1))
  1577. ;; Title line found - check for a following underline.
  1578. (setq ttl (rst-forward-line-looking-at
  1579. 1 'ado-beg-2-1
  1580. #'(lambda (mtcd)
  1581. (when mtcd
  1582. (rst-classify-adornment
  1583. (match-string-no-properties 0) (match-end 0))))))
  1584. ;; Title candidate found if no valid adornment found.
  1585. (funcall cnd-fun (not ttl))))
  1586. (cond
  1587. ((and ttl (rst-Ttl-is-section ttl))
  1588. ttl)
  1589. (cnd-beg
  1590. (rst-Ttl-from-buffer nil nil cnd-beg nil cnd-txt)))))))
  1591. ;; The following function and variables are used to maintain information about
  1592. ;; current section adornment in a buffer local cache. Thus they can be used for
  1593. ;; font-locking and manipulation commands.
  1594. (defvar-local rst-all-ttls-cache nil
  1595. "All section adornments in the buffer as found by `rst-all-ttls'.
  1596. Set to t when no section adornments were found.")
  1597. ;; FIXME: If this variable is set to a different value font-locking of section
  1598. ;; headers is wrong.
  1599. (defvar-local rst-hdr-hierarchy-cache nil
  1600. "Section hierarchy in the buffer as determined by `rst-hdr-hierarchy'.
  1601. Set to t when no section adornments were found.
  1602. Value depends on `rst-all-ttls-cache'.")
  1603. (rst-testcover-add-1value 'rst-reset-section-caches)
  1604. (defun rst-reset-section-caches ()
  1605. "Reset all section cache variables.
  1606. Should be called by interactive functions which deal with sections."
  1607. (setq rst-all-ttls-cache nil
  1608. rst-hdr-hierarchy-cache nil))
  1609. (defun rst-all-ttls-compute ()
  1610. ;; testcover: ok.
  1611. "Return a list of `rst-Ttl' for current buffer with ascending line number."
  1612. (save-excursion
  1613. (save-match-data
  1614. (let (ttls)
  1615. (goto-char (point-min))
  1616. ;; Iterate over all the section titles/adornments in the file.
  1617. (while (re-search-forward (rst-re 'ado-beg-2-1) nil t)
  1618. (let ((ttl (rst-classify-adornment
  1619. (match-string-no-properties 0) (point))))
  1620. (when (and ttl (rst-Ttl-is-section ttl))
  1621. (when (rst-Ttl-hdr ttl)
  1622. (push ttl ttls))
  1623. (goto-char (rst-Ttl-get-end ttl)))))
  1624. (nreverse ttls)))))
  1625. (defun rst-all-ttls ()
  1626. "Return all the section adornments in the current buffer.
  1627. Return a list of `rst-Ttl' with ascending line number.
  1628. Uses and sets `rst-all-ttls-cache'."
  1629. (unless rst-all-ttls-cache
  1630. (setq rst-all-ttls-cache (or (rst-all-ttls-compute) t)))
  1631. (if (eq rst-all-ttls-cache t)
  1632. nil
  1633. (copy-sequence rst-all-ttls-cache)))
  1634. (defun rst-infer-hdr-hierarchy (hdrs)
  1635. ;; testcover: ok.
  1636. "Build a hierarchy from HDRS.
  1637. HDRS reflects the order in which the headers appear in the
  1638. buffer. Return a `rst-Hdr' list representing the hierarchy of
  1639. headers in the buffer. Indentation is unified."
  1640. (let (ado2indents) ; Associates `rst-Ado' with the set of indents seen for it.
  1641. (dolist (hdr hdrs)
  1642. (let* ((ado (rst-Hdr-ado hdr))
  1643. (indent (rst-Hdr-indent hdr))
  1644. (found (assoc ado ado2indents)))
  1645. (if found
  1646. (setcdr found (cl-adjoin indent (cdr found)))
  1647. (push (list ado indent) ado2indents))))
  1648. (mapcar (cl-function
  1649. (lambda ((ado consistent &rest inconsistent))
  1650. (rst-Hdr-new ado (if inconsistent
  1651. rst-default-indent
  1652. consistent))))
  1653. (nreverse ado2indents))))
  1654. (defun rst-hdr-hierarchy (&optional ignore-position)
  1655. ;; testcover: ok.
  1656. "Return the hierarchy of section titles in the file as a `rst-Hdr' list.
  1657. Each returned element may be used directly to create a section
  1658. adornment on that level. If IGNORE-POSITION a title containing
  1659. this position is not taken into account when building the
  1660. hierarchy unless it appears again elsewhere. This catches cases
  1661. where the current title is edited and may not be final regarding
  1662. its level.
  1663. Uses and sets `rst-hdr-hierarchy-cache' unless IGNORE-POSITION is
  1664. given."
  1665. (let* ((all-ttls (rst-all-ttls))
  1666. (ignore-ttl
  1667. (if ignore-position
  1668. (cl-find-if
  1669. #'(lambda (ttl)
  1670. (equal (rst-Ttl-contains ttl ignore-position) 0))
  1671. all-ttls)))
  1672. (really-ignore
  1673. (if ignore-ttl
  1674. (<= (cl-count-if
  1675. #'(lambda (ttl)
  1676. (rst-Ado-equal (rst-Ttl-ado ignore-ttl)
  1677. (rst-Ttl-ado ttl)))
  1678. all-ttls)
  1679. 1)))
  1680. (real-ttls (delq (if really-ignore ignore-ttl) all-ttls)))
  1681. (copy-sequence ; Protect cache.
  1682. (if (and (not ignore-position) rst-hdr-hierarchy-cache)
  1683. (if (eq rst-hdr-hierarchy-cache t)
  1684. nil
  1685. rst-hdr-hierarchy-cache)
  1686. (let ((r (rst-infer-hdr-hierarchy (mapcar #'rst-Ttl-hdr real-ttls))))
  1687. (setq rst-hdr-hierarchy-cache
  1688. (if ignore-position
  1689. ;; Clear cache reflecting that a possible update is not
  1690. ;; reflected.
  1691. nil
  1692. (or r t)))
  1693. r)))))
  1694. (defun rst-all-ttls-with-level ()
  1695. ;; testcover: ok.
  1696. "Return the section adornments with levels set according to hierarchy.
  1697. Return a list of (`rst-Ttl' . LEVEL) with ascending line number."
  1698. (let ((hier (rst-Hdr-ado-map (rst-hdr-hierarchy))))
  1699. (mapcar
  1700. #'(lambda (ttl)
  1701. (cons ttl (rst-Ado-position (rst-Ttl-ado ttl) hier)))
  1702. (rst-all-ttls))))
  1703. (defun rst-get-previous-hdr ()
  1704. "Return the `rst-Hdr' before point or nil if none."
  1705. (let ((prev (cl-find-if #'(lambda (ttl)
  1706. (< (rst-Ttl-contains ttl (point)) 0))
  1707. (rst-all-ttls)
  1708. :from-end t)))
  1709. (and prev (rst-Ttl-hdr prev))))
  1710. (defun rst-adornment-complete-p (ado indent)
  1711. ;; testcover: ok.
  1712. "Return t if the adornment ADO around point is complete using INDENT.
  1713. The adornment is complete if it is a completely correct
  1714. reStructuredText adornment for the title line at point. This
  1715. includes indentation and correct length of adornment lines."
  1716. ;; Note: we assume that the detection of the overline as being the underline
  1717. ;; of a preceding title has already been detected, and has been eliminated
  1718. ;; from the adornment that is given to us.
  1719. (let ((exps (list "^" (rst-Ado-char ado)
  1720. (format "\\{%d\\}"
  1721. (+ (save-excursion
  1722. ;; Determine last column of title.
  1723. (end-of-line)
  1724. (current-column))
  1725. indent)) "$")))
  1726. (and (rst-forward-line-looking-at +1 exps)
  1727. (or (rst-Ado-is-simple ado)
  1728. (rst-forward-line-looking-at -1 exps))
  1729. t))) ; Normalize return value.
  1730. (defun rst-next-hdr (hdr hier prev down)
  1731. ;; testcover: ok.
  1732. "Return the next best `rst-Hdr' upward from HDR.
  1733. Consider existing hierarchy HIER and preferred headers. PREV may
  1734. be a previous `rst-Hdr' which may be taken into account. If DOWN
  1735. return the next best `rst-Hdr' downward instead. Return nil in
  1736. HIER is nil."
  1737. (let* ((normalized-hier (if down
  1738. hier
  1739. (reverse hier)))
  1740. (fnd (rst-Hdr-member-ado hdr normalized-hier))
  1741. (prev-fnd (and prev (rst-Hdr-member-ado prev normalized-hier))))
  1742. (or
  1743. ;; Next entry in existing hierarchy if it exists.
  1744. (cadr fnd)
  1745. (if fnd
  1746. ;; If current header is found try introducing a new one from preferred
  1747. ;; hierarchy.
  1748. (rst-new-preferred-hdr hier prev)
  1749. ;; If not found try using previous header.
  1750. (if down
  1751. (cadr prev-fnd)
  1752. (car prev-fnd)))
  1753. ;; All failed - rotate by using first from normalized existing hierarchy.
  1754. (car normalized-hier))))
  1755. ;; FIXME: A line "``/`` full" is not accepted as a section title.
  1756. (defun rst-adjust (pfxarg)
  1757. ;; testcover: ok.
  1758. "Auto-adjust the adornment around point.
  1759. Adjust/rotate the section adornment for the section title around
  1760. point or promote/demote the adornments inside the region,
  1761. depending on whether the region is active. This function is meant
  1762. to be invoked possibly multiple times, and can vary its behavior
  1763. with a positive PFXARG (toggle style), or with a negative
  1764. PFXARG (alternate behavior).
  1765. This function is a bit of a swiss knife. It is meant to adjust
  1766. the adornments of a section title in reStructuredText. It tries
  1767. to deal with all the possible cases gracefully and to do \"the
  1768. right thing\" in all cases.
  1769. See the documentations of `rst-adjust-section' and
  1770. `rst-adjust-region' for full details.
  1771. The method can take either (but not both) of
  1772. a. a (non-negative) prefix argument, which means to toggle the
  1773. adornment style. Invoke with a prefix argument for example;
  1774. b. a negative numerical argument, which generally inverts the
  1775. direction of search in the file or hierarchy. Invoke with C--
  1776. prefix for example."
  1777. (interactive "P")
  1778. (let* ((origpt (point-marker))
  1779. (reverse-direction (and pfxarg (< (prefix-numeric-value pfxarg) 0)))
  1780. (toggle-style (and pfxarg (not reverse-direction))))
  1781. (if (use-region-p)
  1782. (rst-adjust-region (and pfxarg t))
  1783. (let ((msg (rst-adjust-section toggle-style reverse-direction)))
  1784. (when msg
  1785. (apply #'message msg))))
  1786. (run-hooks 'rst-adjust-hook)
  1787. (rst-reset-section-caches)
  1788. (set-marker
  1789. (goto-char origpt) nil)))
  1790. (defcustom rst-adjust-hook nil
  1791. "Hooks to be run after running `rst-adjust'."
  1792. :group 'rst-adjust
  1793. :type '(hook)
  1794. :package-version '(rst . "1.1.0"))
  1795. (rst-testcover-defcustom)
  1796. (defcustom rst-new-adornment-down nil
  1797. "Controls level of new adornment for section headers."
  1798. :group 'rst-adjust
  1799. :type '(choice
  1800. (const :tag "Same level as previous one" nil)
  1801. (const :tag "One level down relative to the previous one" t))
  1802. :package-version '(rst . "1.1.0"))
  1803. (rst-testcover-defcustom)
  1804. (defun rst-adjust-adornment (pfxarg)
  1805. "Call `rst-adjust-section' interactively.
  1806. Keep this for compatibility for older bindings (are there any?).
  1807. Argument PFXARG has the same meaning as for `rst-adjust'."
  1808. (interactive "P")
  1809. (let* ((reverse-direction (and pfxarg (< (prefix-numeric-value pfxarg) 0)))
  1810. (toggle-style (and pfxarg (not reverse-direction))))
  1811. (rst-adjust-section toggle-style reverse-direction)))
  1812. (defun rst-adjust-new-hdr (toggle-style reverse ttl)
  1813. ;; testcover: ok.
  1814. "Return a new `rst-Hdr' for `rst-adjust-section' related to TTL.
  1815. TOGGLE-STYLE and REVERSE are from
  1816. `rst-adjust-section'. TOGGLE-STYLE may be consumed and thus is
  1817. returned.
  1818. Return a list (HDR TOGGLE-STYLE MSG...). HDR is the result or
  1819. nil. TOGGLE-STYLE is the new TOGGLE-STYLE to use in the
  1820. caller. MSG is a list which is non-empty in case HDR is nil
  1821. giving an argument list for `message'."
  1822. (save-excursion
  1823. (goto-char (rst-Ttl-get-title-beginning ttl))
  1824. (let ((indent (rst-Ttl-indent ttl))
  1825. (ado (rst-Ttl-ado ttl))
  1826. (prev (rst-get-previous-hdr))
  1827. hdr-msg)
  1828. (setq
  1829. hdr-msg
  1830. (cond
  1831. ((rst-Ttl-is-candidate ttl)
  1832. ;; Case 1: No adornment at all.
  1833. (let ((hier (rst-hdr-hierarchy)))
  1834. (if prev
  1835. ;; Previous header exists - use it.
  1836. (cond
  1837. ;; Customization and parameters require that the previous level
  1838. ;; is used - use it as is.
  1839. ((or (and rst-new-adornment-down reverse)
  1840. (and (not rst-new-adornment-down) (not reverse)))
  1841. prev)
  1842. ;; Advance one level down.
  1843. ((rst-next-hdr prev hier prev t))
  1844. ("Neither hierarchy nor preferences can suggest a deeper header"))
  1845. ;; First header in the buffer - use the first adornment from
  1846. ;; preferences or hierarchy.
  1847. (let ((p (car (rst-Hdr-preferred-adornments)))
  1848. (h (car hier)))
  1849. (cond
  1850. ((if reverse
  1851. ;; Prefer hierarchy for downwards
  1852. (or h p)
  1853. ;; Prefer preferences for upwards
  1854. (or p h)))
  1855. ("No preferences to suggest a top level from"))))))
  1856. ((not (rst-adornment-complete-p ado indent))
  1857. ;; Case 2: Incomplete adornment.
  1858. ;; Use lax since indentation might not match suggestion.
  1859. (rst-Hdr-new-lax ado indent))
  1860. ;; Case 3: Complete adornment exists from here on.
  1861. (toggle-style
  1862. ;; Simply switch the style of the current adornment.
  1863. (setq toggle-style nil) ; Remember toggling has been done.
  1864. (rst-Hdr-new-invert ado rst-default-indent))
  1865. (t
  1866. ;; Rotate, ignoring a sole adornment around the current line.
  1867. (let ((hier (rst-hdr-hierarchy (point))))
  1868. (cond
  1869. ;; Next header can be determined from hierarchy or preferences.
  1870. ((rst-next-hdr
  1871. ;; Use lax since indentation might not match suggestion.
  1872. (rst-Hdr-new-lax ado indent) hier prev reverse))
  1873. ;; No next header found.
  1874. ("No preferences or hierarchy to suggest another level from"))))))
  1875. (if (stringp hdr-msg)
  1876. (list nil toggle-style hdr-msg)
  1877. (list hdr-msg toggle-style)))))
  1878. (defun rst-adjust-section (toggle-style reverse)
  1879. ;; testcover: ok.
  1880. "Adjust/rotate the section adornment for the section title around point.
  1881. The action this function takes depends on context around the
  1882. point, and it is meant to be invoked possibly more than once to
  1883. rotate among the various possibilities. Basically, this function
  1884. deals with:
  1885. - adding an adornment if the title does not have one;
  1886. - adjusting the length of the underline characters to fit a
  1887. modified title;
  1888. - rotating the adornment in the set of already existing
  1889. sectioning adornments used in the file;
  1890. - switching between simple and over-and-under styles by giving
  1891. TOGGLE-STYLE.
  1892. Return nil if the function did something. If the function were
  1893. not able to do something return an argument list for `message' to
  1894. inform the user about what failed.
  1895. The following is a detailed description but you should normally
  1896. not have to read it.
  1897. Before applying the adornment change, the cursor is placed on the
  1898. closest line that could contain a section title if such is found
  1899. around the cursor. Then the following cases are distinguished.
  1900. * Case 1: No Adornment
  1901. If the current line has no adornment around it,
  1902. - search for a previous adornment, and apply this adornment (unless
  1903. `rst-new-adornment-down') or one level lower (otherwise) to the current
  1904. line. If there is no defined level below this previous adornment, we
  1905. suggest the most appropriate of the `rst-preferred-adornments'.
  1906. If REVERSE is true, we simply use the previous adornment found
  1907. directly.
  1908. - if there is no adornment found in the given direction, we use the first of
  1909. `rst-preferred-adornments'.
  1910. TOGGLE-STYLE forces a toggle of the prescribed adornment style.
  1911. * Case 2: Incomplete Adornment
  1912. If the current line does have an existing adornment, but the adornment is
  1913. incomplete, that is, the underline/overline does not extend to exactly the
  1914. end of the title line (it is either too short or too long), we simply extend
  1915. the length of the underlines/overlines to fit exactly the section title.
  1916. If TOGGLE-STYLE we toggle the style of the adornment as well.
  1917. REVERSE has no effect in this case.
  1918. * Case 3: Complete Existing Adornment
  1919. If the adornment is complete (i.e. the underline (overline) length is already
  1920. adjusted to the end of the title line), we rotate the current title's
  1921. adornment according to the adornment hierarchy found in the buffer. This is
  1922. meant to be used potentially multiple times, until the desired adornment is
  1923. found around the title.
  1924. If we hit the boundary of the hierarchy, exactly one choice from the list of
  1925. preferred adornments is suggested/chosen, the first of those adornment that
  1926. has not been seen in the buffer yet, and the next invocation rolls over to
  1927. the other end of the hierarchy (i.e. it cycles).
  1928. If REVERSE is we go up in the hierarchy. Otherwise we go down.
  1929. However, if TOGGLE-STYLE, we do not rotate the adornment, but instead simply
  1930. toggle the style of the current adornment."
  1931. (rst-reset-section-caches)
  1932. (let ((ttl (rst-ttl-at-point)))
  1933. (if (not ttl)
  1934. '("No section header or candidate at point")
  1935. (cl-destructuring-bind
  1936. (hdr toggle-style &rest msg
  1937. &aux
  1938. (indent (rst-Ttl-indent ttl))
  1939. (moved (- (line-number-at-pos (rst-Ttl-get-title-beginning ttl))
  1940. (line-number-at-pos))))
  1941. (rst-adjust-new-hdr toggle-style reverse ttl)
  1942. (if msg
  1943. msg
  1944. (when toggle-style
  1945. (setq hdr (rst-Hdr-new-invert (rst-Hdr-ado hdr) indent)))
  1946. ;; Override indent with present indent if there is some.
  1947. (when (> indent 0)
  1948. ;; Use lax since existing indent may not be valid for new style.
  1949. (setq hdr (rst-Hdr-new-lax (rst-Hdr-ado hdr) indent)))
  1950. (goto-char (rst-Ttl-get-title-beginning ttl))
  1951. (rst-update-section hdr)
  1952. ;; Correct the position of the cursor to more accurately reflect
  1953. ;; where it was located when the function was invoked.
  1954. (unless (zerop moved)
  1955. (1value ; No lines may be left to move.
  1956. (rst-forward-line-strict (- moved)))
  1957. (end-of-line))
  1958. nil)))))
  1959. ;; Maintain an alias for compatibility.
  1960. (defalias 'rst-adjust-section-title 'rst-adjust)
  1961. (defun rst-adjust-region (demote)
  1962. ;; testcover: ok.
  1963. "Promote the section titles within the region.
  1964. With argument DEMOTE or a prefix argument, demote the section
  1965. titles instead. The algorithm used at the boundaries of the
  1966. hierarchy is similar to that used by `rst-adjust-section'."
  1967. (interactive "P")
  1968. (rst-reset-section-caches)
  1969. (let* ((beg (region-beginning))
  1970. (end (region-end))
  1971. (ttls-reg (cl-remove-if-not
  1972. #'(lambda (ttl)
  1973. (and
  1974. (>= (rst-Ttl-contains ttl beg) 0)
  1975. (< (rst-Ttl-contains ttl end) 0)))
  1976. (rst-all-ttls))))
  1977. (save-excursion
  1978. ;; Apply modifications.
  1979. (rst-destructuring-dolist
  1980. ((marker &rest hdr
  1981. &aux (hier (rst-hdr-hierarchy)))
  1982. (mapcar #'(lambda (ttl)
  1983. (cons (copy-marker (rst-Ttl-get-title-beginning ttl))
  1984. (rst-Ttl-hdr ttl)))
  1985. ttls-reg))
  1986. (set-marker
  1987. (goto-char marker) nil)
  1988. ;; `rst-next-hdr' cannot return nil because we apply to a section
  1989. ;; header so there is some hierarchy.
  1990. (rst-update-section (rst-next-hdr hdr hier nil demote)))
  1991. (setq deactivate-mark nil))))
  1992. (defun rst-display-hdr-hierarchy ()
  1993. ;; testcover: ok.
  1994. "Display the current file's section title adornments hierarchy.
  1995. Hierarchy is displayed in a temporary buffer."
  1996. (interactive)
  1997. (rst-reset-section-caches)
  1998. (let ((hdrs (rst-hdr-hierarchy))
  1999. (level 1))
  2000. (with-output-to-temp-buffer "*rest section hierarchy*"
  2001. (with-current-buffer standard-output
  2002. (dolist (hdr hdrs)
  2003. (insert (format "\nSection Level %d" level))
  2004. (rst-update-section hdr)
  2005. (goto-char (point-max))
  2006. (insert "\n")
  2007. (cl-incf level))))))
  2008. ;; Maintain an alias for backward compatibility.
  2009. (defalias 'rst-display-adornments-hierarchy 'rst-display-hdr-hierarchy)
  2010. ;; FIXME: Should accept an argument giving the hierarchy level to start with
  2011. ;; instead of the top of the hierarchy.
  2012. (defun rst-straighten-sections ()
  2013. ;; testcover: ok.
  2014. "Redo the adornments of all section titles in the current buffer.
  2015. This is done using the preferred set of adornments. This can be
  2016. used, for example, when using somebody else's copy of a document,
  2017. in order to adapt it to our preferred style."
  2018. (interactive)
  2019. (rst-reset-section-caches)
  2020. (save-excursion
  2021. (rst-destructuring-dolist
  2022. ((marker &rest level)
  2023. (mapcar
  2024. (cl-function
  2025. (lambda ((ttl &rest level))
  2026. ;; Use markers so edits don't disturb the position.
  2027. (cons (copy-marker (rst-Ttl-get-title-beginning ttl)) level)))
  2028. (rst-all-ttls-with-level)))
  2029. (set-marker
  2030. (goto-char marker) nil)
  2031. (rst-update-section (nth level (rst-Hdr-preferred-adornments))))))
  2032. ;; Maintain an alias for compatibility.
  2033. (defalias 'rst-straighten-adornments 'rst-straighten-sections)
  2034. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2035. ;; Insert list items
  2036. ;; Borrowed from a2r.el (version 1.3), by Lawrence Mitchell <wence@gmx.li>. I
  2037. ;; needed to make some tiny changes to the functions, so I put it here.
  2038. ;; -- Wei-Wei Guo
  2039. (defconst rst-arabic-to-roman
  2040. '((1000 . "M") (900 . "CM") (500 . "D") (400 . "CD")
  2041. (100 . "C") (90 . "XC") (50 . "L") (40 . "XL")
  2042. (10 . "X") (9 . "IX") (5 . "V") (4 . "IV")
  2043. (1 . "I"))
  2044. "List of maps between Arabic numbers and their Roman numeral equivalents.")
  2045. (defun rst-arabic-to-roman (num)
  2046. ;; testcover: ok.
  2047. "Convert Arabic number NUM to its Roman numeral representation.
  2048. Obviously, NUM must be greater than zero. Don't blame me, blame the
  2049. Romans, I mean \"what have the Romans ever _done_ for /us/?\" (with
  2050. apologies to Monty Python)."
  2051. (cl-check-type num (integer 1 *))
  2052. (let ((map rst-arabic-to-roman)
  2053. (r ""))
  2054. (while (and map (> num 0))
  2055. (cl-destructuring-bind ((val &rest sym) &rest next) map
  2056. (if (>= num val)
  2057. (setq r (concat r sym)
  2058. num (- num val))
  2059. (setq map next))))
  2060. r))
  2061. (defun rst-roman-to-arabic (string)
  2062. ;; testcover: ok.
  2063. "Convert STRING of Roman numerals to an Arabic number.
  2064. If STRING contains a letter which isn't a valid Roman numeral,
  2065. the rest of the string from that point onwards is ignored.
  2066. Hence:
  2067. MMD == 2500
  2068. and
  2069. MMDFLXXVI == 2500."
  2070. (cl-check-type string string)
  2071. (cl-check-type string (satisfies (lambda (s)
  2072. (not (equal s ""))))
  2073. "Roman number may not be an empty string.")
  2074. (let ((res 0)
  2075. (map rst-arabic-to-roman))
  2076. (save-match-data
  2077. (while map
  2078. (cl-destructuring-bind ((val &rest sym) &rest next) map
  2079. (if (string-match (concat "^" sym) string)
  2080. (setq res (+ res val)
  2081. string (replace-match "" nil t string))
  2082. (setq map next))))
  2083. (cl-check-type string (satisfies (lambda (s)
  2084. (equal s "")))
  2085. "Invalid characters in roman number")
  2086. res)))
  2087. ;; End of borrow.
  2088. ;; FIXME: All the following code should not consider single lines as items but
  2089. ;; paragraphs as reST does.
  2090. (defun rst-insert-list-new-tag (tag)
  2091. ;; testcover: ok.
  2092. "Insert first item of a new list tagged with TAG.
  2093. Adding a new list might consider three situations:
  2094. (a) Current line is a blank line.
  2095. (b) Previous line is a blank line.
  2096. (c) Following line is a blank line.
  2097. When (a) and (b), just add the new list at current line.
  2098. when (a) and not (b), a blank line is added before adding the new list.
  2099. When not (a), first forward point to the end of the line, and add two
  2100. blank lines, then add the new list.
  2101. Other situations are just ignored and left to users themselves."
  2102. ;; FIXME: Following line is not considered at all.
  2103. (let ((pfx-nls
  2104. ;; FIXME: Doesn't work properly for white-space line. See
  2105. ;; `rst-insert-list-new-BUGS'.
  2106. (if (rst-forward-line-looking-at 0 'lin-end)
  2107. (if (not (rst-forward-line-looking-at -1 'lin-end #'not))
  2108. 0
  2109. 1)
  2110. 2)))
  2111. (end-of-line)
  2112. ;; FIXME: The indentation is not fixed to a single space by the syntax. May
  2113. ;; be this should be configurable or rather taken from the context.
  2114. (insert (make-string pfx-nls ?\n) tag " ")))
  2115. (defconst rst-initial-items
  2116. (append (mapcar #'char-to-string rst-bullets)
  2117. (let (vals)
  2118. (dolist (fmt '("%s." "(%s)" "%s)"))
  2119. (dolist (c '("#" "1" "a" "A" "I" "i"))
  2120. (push (format fmt c) vals)))
  2121. (nreverse vals)))
  2122. "List of initial items. It's a collection of bullets and enumerations.")
  2123. (defun rst-insert-list-new-item ()
  2124. ;; testcover: ok.
  2125. "Insert a new list item.
  2126. User is asked to select the item style first, for example (a), i), +.
  2127. Use TAB for completion and choices.
  2128. If user selects bullets or #, it's just added with position arranged by
  2129. `rst-insert-list-new-tag'.
  2130. If user selects enumerations, a further prompt is given. User need to
  2131. input a starting item, for example 'e' for 'A)' style. The position is
  2132. also arranged by `rst-insert-list-new-tag'."
  2133. (let* ((itemstyle (completing-read
  2134. "Select preferred item style [#.]: "
  2135. rst-initial-items nil t nil nil "#."))
  2136. (cnt (if (string-match (rst-re 'cntexp-tag) itemstyle)
  2137. (match-string 0 itemstyle)))
  2138. (no
  2139. (save-match-data
  2140. (cond
  2141. ((equal cnt "a")
  2142. (let ((itemno (read-string "Give starting value [a]: "
  2143. nil nil "a")))
  2144. (downcase (substring itemno 0 1))))
  2145. ((equal cnt "A")
  2146. (let ((itemno (read-string "Give starting value [A]: "
  2147. nil nil "A")))
  2148. (upcase (substring itemno 0 1))))
  2149. ((equal cnt "I")
  2150. (let ((itemno (read-number "Give starting value [1]: " 1)))
  2151. (rst-arabic-to-roman itemno)))
  2152. ((equal cnt "i")
  2153. (let ((itemno (read-number "Give starting value [1]: " 1)))
  2154. (downcase (rst-arabic-to-roman itemno))))
  2155. ((equal cnt "1")
  2156. (let ((itemno (read-number "Give starting value [1]: " 1)))
  2157. (number-to-string itemno)))))))
  2158. (if no
  2159. (setq itemstyle (replace-match no t t itemstyle)))
  2160. (rst-insert-list-new-tag itemstyle)))
  2161. (defcustom rst-preferred-bullets
  2162. '(?* ?- ?+)
  2163. "List of favorite bullets."
  2164. :group 'rst
  2165. :type `(repeat
  2166. (choice ,@(mapcar #'(lambda (char)
  2167. (list 'const
  2168. :tag (char-to-string char) char))
  2169. rst-bullets)))
  2170. :package-version '(rst . "1.1.0"))
  2171. (rst-testcover-defcustom)
  2172. (defun rst-insert-list-continue (ind tag tab prefer-roman)
  2173. ;; testcover: ok.
  2174. "Insert a new list tag after the current line according to style.
  2175. Style is defined by indentation IND, TAG and suffix TAB. If
  2176. PREFER-ROMAN roman numbering is preferred over using letters."
  2177. (end-of-line)
  2178. (insert
  2179. ;; FIXME: Separating lines must be possible.
  2180. "\n"
  2181. ind
  2182. (save-match-data
  2183. (if (not (string-match (rst-re 'cntexp-tag) tag))
  2184. tag
  2185. (let ((pfx (substring tag 0 (match-beginning 0)))
  2186. (cnt (match-string 0 tag))
  2187. (sfx (substring tag (match-end 0))))
  2188. (concat
  2189. pfx
  2190. (cond
  2191. ((string-match (rst-re 'num-tag) cnt)
  2192. (number-to-string (1+ (string-to-number (match-string 0 cnt)))))
  2193. ((and
  2194. (string-match (rst-re 'rom-tag) cnt)
  2195. (save-match-data
  2196. (if (string-match (rst-re 'ltr-tag) cnt) ; Also a letter tag.
  2197. (save-excursion
  2198. ;; FIXME: Assumes one line list items without separating
  2199. ;; empty lines.
  2200. ;; Use of `rst-forward-line-looking-at' is very difficult
  2201. ;; here so don't do it.
  2202. (if (and (rst-forward-line-strict -1)
  2203. (looking-at (rst-re 'enmexp-beg)))
  2204. (string-match
  2205. (rst-re 'rom-tag)
  2206. (match-string 0)) ; Previous was a roman tag.
  2207. prefer-roman)) ; Don't know - use flag.
  2208. t))) ; Not a letter tag.
  2209. (let* ((old (match-string 0 cnt))
  2210. (new (rst-arabic-to-roman
  2211. (1+ (rst-roman-to-arabic (upcase old))))))
  2212. (if (equal old (upcase old))
  2213. (upcase new)
  2214. (downcase new))))
  2215. ((string-match (rst-re 'ltr-tag) cnt)
  2216. (char-to-string (1+ (string-to-char (match-string 0 cnt))))))
  2217. sfx))))
  2218. tab))
  2219. ;; FIXME: At least the continuation may be folded into
  2220. ;; `newline-and-indent`. However, this may not be wanted by everyone so
  2221. ;; it should be possible to switch this off.
  2222. (defun rst-insert-list (&optional prefer-roman)
  2223. ;; testcover: ok.
  2224. "Insert a list item at the current point.
  2225. The command can insert a new list or a continuing list. When it is called at a
  2226. non-list line, it will promote to insert new list. When it is called at a list
  2227. line, it will insert a list with the same list style.
  2228. 1. When inserting a new list:
  2229. User is asked to select the item style first, for example (a), i), +. Use TAB
  2230. for completion and choices.
  2231. (a) If user selects bullets or #, it's just added.
  2232. (b) If user selects enumerations, a further prompt is given. User needs to
  2233. input a starting item, for example `e' for `A)' style.
  2234. The position of the new list is arranged according to whether or not the
  2235. current line and the previous line are blank lines.
  2236. 2. When continuing a list, one thing needs to be noticed:
  2237. List style alphabetical list, such as `a.', and roman numerical list, such as
  2238. `i.', have some overlapping items, for example `v.' The function can deal with
  2239. the problem elegantly in most situations. But when those overlapped list are
  2240. preceded by a blank line, it is hard to determine which type to use
  2241. automatically. The function uses alphabetical list by default. If you want
  2242. roman numerical list, just use a prefix to set PREFER-ROMAN."
  2243. (interactive "P")
  2244. (save-match-data
  2245. (1value
  2246. (rst-forward-line-strict 0))
  2247. ;; FIXME: Finds only tags in single line items. Multi-line items should be
  2248. ;; considered as well.
  2249. ;; Using `rst-forward-line-looking-at' is more complicated so don't do it.
  2250. (if (looking-at (rst-re 'itmany-beg-1))
  2251. (rst-insert-list-continue
  2252. (buffer-substring-no-properties
  2253. (match-beginning 0) (match-beginning 1))
  2254. (match-string 1)
  2255. (buffer-substring-no-properties (match-end 1) (match-end 0))
  2256. prefer-roman)
  2257. (rst-insert-list-new-item))))
  2258. ;; FIXME: This is wrong because it misses prefixed lines without intervening
  2259. ;; new line. See `rst-straighten-bullets-region-BUGS' and
  2260. ;; `rst-find-begs-BUGS'.
  2261. (defun rst-find-begs (beg end rst-re-beg)
  2262. ;; testcover: ok.
  2263. "Return the positions of begs in region BEG to END.
  2264. RST-RE-BEG is a `rst-re' argument and matched at the beginning of
  2265. a line. Return a list of (POINT . COLUMN) where POINT gives the
  2266. point after indentation and COLUMN gives its column. The list is
  2267. ordered by POINT."
  2268. (let (r)
  2269. (save-match-data
  2270. (save-excursion
  2271. ;; FIXME refactoring: Consider making this construct a macro looping
  2272. ;; over the lines.
  2273. (goto-char beg)
  2274. (1value
  2275. (rst-forward-line-strict 0))
  2276. (while (< (point) end)
  2277. (let ((clm (current-indentation)))
  2278. ;; FIXME refactoring: Consider using `rst-forward-line-looking-at'.
  2279. (when (and
  2280. (looking-at (rst-re rst-re-beg)) ; Start found
  2281. (not (rst-forward-line-looking-at
  2282. -1 'lin-end
  2283. #'(lambda (mtcd) ; Previous line exists and is...
  2284. (and
  2285. (not mtcd) ; non-empty,
  2286. (<= (current-indentation) clm) ; less indented
  2287. (not (and (= (current-indentation) clm)
  2288. ; not a beg at same level.
  2289. (looking-at (rst-re rst-re-beg)))))))))
  2290. (back-to-indentation)
  2291. (push (cons (point) clm) r)))
  2292. (1value ; At least one line is moved in this loop.
  2293. (rst-forward-line-strict 1 end)))))
  2294. (nreverse r)))
  2295. (defun rst-straighten-bullets-region (beg end)
  2296. ;; testcover: ok.
  2297. "Make all the bulleted list items in the region from BEG to END consistent.
  2298. Use this after you have merged multiple bulleted lists to make
  2299. them use the preferred bullet characters given by
  2300. `rst-preferred-bullets' for each level. If bullets are found on
  2301. levels beyond the `rst-preferred-bullets' list, they are not
  2302. modified."
  2303. (interactive "r")
  2304. (save-excursion
  2305. (let (clm2pnts) ; Map a column to a list of points at this column.
  2306. (rst-destructuring-dolist
  2307. ((point &rest column
  2308. &aux (found (assoc column clm2pnts)))
  2309. (rst-find-begs beg end 'bul-beg))
  2310. (if found
  2311. ;;; (push point (cdr found)) ; FIXME: Doesn't work with `testcover'.
  2312. (setcdr found (cons point (cdr found))) ; Synonym.
  2313. (push (list column point) clm2pnts)))
  2314. (rst-destructuring-dolist
  2315. ((bullet _clm &rest pnts)
  2316. ;; Zip preferred bullets and sorted columns associating a bullet
  2317. ;; with a column and all the points this column is found.
  2318. (cl-mapcar #'(lambda (bullet clm2pnt)
  2319. (cons bullet clm2pnt))
  2320. rst-preferred-bullets
  2321. (sort clm2pnts #'car-less-than-car)))
  2322. ;; Replace the bullets by the preferred ones.
  2323. (dolist (pnt pnts)
  2324. (goto-char pnt)
  2325. ;; FIXME: Assumes bullet to replace is a single char.
  2326. (delete-char 1)
  2327. (insert bullet))))))
  2328. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2329. ;; Table of contents
  2330. (defun rst-all-stn ()
  2331. ;; testcover: ok.
  2332. "Return the hierarchical tree of sections as a top level `rst-Stn'.
  2333. Return value satisfies `rst-Stn-is-top' or is nil for no
  2334. sections."
  2335. (cdr (rst-remaining-stn (rst-all-ttls-with-level) -1)))
  2336. (defun rst-remaining-stn (unprocessed expected)
  2337. ;; testcover: ok.
  2338. "Process the first entry of UNPROCESSED expected to be on level EXPECTED.
  2339. UNPROCESSED is the remaining list of (`rst-Ttl' . LEVEL) entries.
  2340. Return (REMAINING . STN) for the first entry of UNPROCESSED.
  2341. REMAINING is the list of still unprocessed entries. STN is a
  2342. `rst-Stn' or nil if UNPROCESSED is empty."
  2343. (if (not unprocessed)
  2344. (1value
  2345. (cons nil nil))
  2346. (cl-destructuring-bind
  2347. ((ttl &rest level) &rest next
  2348. &aux fnd children)
  2349. unprocessed
  2350. (when (= level expected)
  2351. ;; Consume the current entry and create the current node with it.
  2352. (setq fnd ttl)
  2353. (setq unprocessed next))
  2354. ;; Build the child nodes as long as they have deeper level.
  2355. (while (and unprocessed (> (cdar unprocessed) expected))
  2356. (cl-destructuring-bind (remaining &rest stn)
  2357. (rst-remaining-stn unprocessed (1+ expected))
  2358. (when stn
  2359. (push stn children))
  2360. (setq unprocessed remaining)))
  2361. (cons unprocessed
  2362. (when (or fnd children)
  2363. (rst-Stn-new fnd expected (nreverse children)))))))
  2364. (defun rst-stn-containing-point (stn &optional point)
  2365. ;; testcover: ok.
  2366. "Return `rst-Stn' in STN before POINT or nil if in no section.
  2367. POINT defaults to the current point. STN may be nil for no
  2368. section headers at all."
  2369. (when stn
  2370. (setq point (or point (point)))
  2371. (when (>= point (rst-Stn-get-title-beginning stn))
  2372. ;; Point may be in this section or a child.
  2373. (let ((in-child (cl-find-if
  2374. #'(lambda (child)
  2375. (>= point (rst-Stn-get-title-beginning child)))
  2376. (rst-Stn-children stn)
  2377. :from-end t)))
  2378. (if in-child
  2379. (rst-stn-containing-point in-child point)
  2380. stn)))))
  2381. (defgroup rst-toc nil
  2382. "Settings for reStructuredText table of contents."
  2383. :group 'rst
  2384. :version "21.1")
  2385. (defcustom rst-toc-indent 2
  2386. "Indentation for table-of-contents display.
  2387. Also used for formatting insertion, when numbering is disabled."
  2388. :type 'integer
  2389. :group 'rst-toc)
  2390. (rst-testcover-defcustom)
  2391. (defcustom rst-toc-insert-style 'fixed
  2392. "Insertion style for table-of-contents.
  2393. Set this to one of the following values to determine numbering and
  2394. indentation style:
  2395. - `plain': no numbering (fixed indentation)
  2396. - `fixed': numbering, but fixed indentation
  2397. - `aligned': numbering, titles aligned under each other
  2398. - `listed': titles as list items"
  2399. :type '(choice (const plain)
  2400. (const fixed)
  2401. (const aligned)
  2402. (const listed))
  2403. :group 'rst-toc)
  2404. (rst-testcover-defcustom)
  2405. (defcustom rst-toc-insert-number-separator " "
  2406. "Separator that goes between the TOC number and the title."
  2407. :type 'string
  2408. :group 'rst-toc)
  2409. (rst-testcover-defcustom)
  2410. (defcustom rst-toc-insert-max-level nil
  2411. "If non-nil, maximum depth of the inserted TOC."
  2412. :type '(choice (const nil) integer)
  2413. :group 'rst-toc)
  2414. (rst-testcover-defcustom)
  2415. (defconst rst-toc-link-keymap
  2416. (let ((map (make-sparse-keymap)))
  2417. (define-key map [mouse-1] 'rst-toc-mouse-follow-link)
  2418. map)
  2419. "Keymap used for links in TOC.")
  2420. (defun rst-toc-insert (&optional max-level)
  2421. ;; testcover: ok.
  2422. "Insert the table of contents of the current section at the current column.
  2423. By default the top level is ignored if there is only one, because
  2424. we assume that the document will have a single title. A numeric
  2425. prefix argument MAX-LEVEL overrides `rst-toc-insert-max-level'.
  2426. Text in the line beyond column is deleted."
  2427. (interactive "P")
  2428. (rst-reset-section-caches)
  2429. (let ((pt-stn (rst-stn-containing-point (rst-all-stn))))
  2430. (when pt-stn
  2431. (let ((max
  2432. (if (and (integerp max-level)
  2433. (> (prefix-numeric-value max-level) 0))
  2434. (prefix-numeric-value max-level)
  2435. rst-toc-insert-max-level))
  2436. (ind (current-column))
  2437. (buf (current-buffer))
  2438. (tabs indent-tabs-mode) ; Copy buffer local value.
  2439. txt)
  2440. (setq txt
  2441. ;; Render to temporary buffer so markers are created correctly.
  2442. (with-temp-buffer
  2443. (rst-toc-insert-tree pt-stn buf rst-toc-insert-style max
  2444. rst-toc-link-keymap nil)
  2445. (goto-char (point-min))
  2446. (when (rst-forward-line-strict 1)
  2447. ;; There are lines to indent.
  2448. (let ((indent-tabs-mode tabs))
  2449. (indent-rigidly (point) (point-max) ind)))
  2450. (buffer-string)))
  2451. (unless (zerop (length txt))
  2452. ;; Delete possible trailing text.
  2453. (delete-region (point) (line-beginning-position 2))
  2454. (insert txt)
  2455. (backward-char 1))))))
  2456. (defun rst-toc-insert-link (pfx stn buf keymap)
  2457. ;; testcover: ok.
  2458. "Insert text of STN in BUF as a linked section reference at point.
  2459. If KEYMAP use this as keymap property. PFX is inserted before text."
  2460. (let ((beg (point)))
  2461. (insert pfx)
  2462. (insert (rst-Stn-get-text stn))
  2463. (put-text-property beg (point) 'mouse-face 'highlight)
  2464. (insert "\n")
  2465. (put-text-property
  2466. beg (point) 'rst-toc-target
  2467. (set-marker (make-marker) (rst-Stn-get-title-beginning stn) buf))
  2468. (when keymap
  2469. (put-text-property beg (point) 'keymap keymap))))
  2470. (defun rst-toc-get-link (link-buf link-pnt)
  2471. ;; testcover: ok.
  2472. "Return the link from text property at LINK-PNT in LINK-BUF."
  2473. (let ((mrkr (get-text-property link-pnt 'rst-toc-target link-buf)))
  2474. (unless mrkr
  2475. (error "No section on this line"))
  2476. (unless (buffer-live-p (marker-buffer mrkr))
  2477. (error "Buffer for this section was killed"))
  2478. mrkr))
  2479. (defun rst-toc-insert-tree (stn buf style depth keymap tgt-stn)
  2480. ;; testcover: ok.
  2481. "Insert table of contents of tree below top node STN in buffer BUF.
  2482. STYLE is the style to use and must be one of the symbols allowed
  2483. for `rst-toc-insert-style'. DEPTH is the maximum relative depth
  2484. from STN to insert or nil for no maximum depth. See
  2485. `rst-toc-insert-link' for KEYMAP. Return beginning of title line
  2486. if TGT-STN is rendered or nil if not rendered or TGT-STN is nil.
  2487. Just return nil if STN is nil."
  2488. (when stn
  2489. (rst-toc-insert-children (rst-Stn-children stn) buf style depth 0 "" keymap
  2490. tgt-stn)))
  2491. (defun rst-toc-insert-children (children buf style depth indent numbering
  2492. keymap tgt-stn)
  2493. ;; testcover: ok.
  2494. "In the current buffer at point insert CHILDREN in BUF to table of contents.
  2495. See `rst-toc-insert-tree' for STYLE, DEPTH and TGT-STN. See
  2496. `rst-toc-insert-stn' for INDENT and NUMBERING. See
  2497. `rst-toc-insert-link' for KEYMAP."
  2498. (let ((count 1)
  2499. ;; Child numbering is done from the parent.
  2500. (num-fmt (format "%%%dd"
  2501. (1+ (floor (log (1+ (length children)) 10)))))
  2502. fnd)
  2503. (when (not (equal numbering ""))
  2504. ;; Add separating dot to existing numbering.
  2505. (setq numbering (concat numbering ".")))
  2506. (dolist (child children fnd)
  2507. (setq fnd
  2508. (or (rst-toc-insert-stn child buf style depth indent
  2509. (concat numbering (format num-fmt count))
  2510. keymap tgt-stn) fnd))
  2511. (cl-incf count))))
  2512. ;; FIXME refactoring: Use `rst-Stn-buffer' instead of `buf'.
  2513. (defun rst-toc-insert-stn (stn buf style depth indent numbering keymap tgt-stn)
  2514. ;; testcover: ok.
  2515. "In the current buffer at point insert STN in BUF into table of contents.
  2516. See `rst-toc-insert-tree' for STYLE, DEPTH and TGT-STN. INDENT
  2517. is the indentation depth to use for STN. NUMBERING is the prefix
  2518. numbering for STN. See `rst-toc-insert-link' for KEYMAP."
  2519. (when (or (not depth) (> depth 0))
  2520. (cl-destructuring-bind
  2521. (pfx add
  2522. &aux (fnd (when (and tgt-stn
  2523. (equal (rst-Stn-get-title-beginning stn)
  2524. (rst-Stn-get-title-beginning tgt-stn)))
  2525. (point))))
  2526. (cond
  2527. ((eq style 'plain)
  2528. (list "" rst-toc-indent))
  2529. ((eq style 'fixed)
  2530. (list (concat numbering rst-toc-insert-number-separator)
  2531. rst-toc-indent))
  2532. ((eq style 'aligned)
  2533. (list (concat numbering rst-toc-insert-number-separator)
  2534. (+ (length numbering)
  2535. (length rst-toc-insert-number-separator))))
  2536. ((eq style 'listed)
  2537. (list (format "%c " (car rst-preferred-bullets)) 2)))
  2538. ;; Indent using spaces so buffer characteristics like `indent-tabs-mode'
  2539. ;; do not matter.
  2540. (rst-toc-insert-link (concat (make-string indent ? ) pfx) stn buf keymap)
  2541. (or (rst-toc-insert-children (rst-Stn-children stn) buf style
  2542. (when depth
  2543. (1- depth))
  2544. (+ indent add) numbering keymap tgt-stn)
  2545. fnd))))
  2546. (defun rst-toc-update ()
  2547. ;; testcover: ok.
  2548. "Automatically find the contents section of a document and update.
  2549. Updates the inserted TOC if present. You can use this in your
  2550. file-write hook to always make it up-to-date automatically."
  2551. (interactive)
  2552. (save-match-data
  2553. (save-excursion
  2554. ;; Find and delete an existing comment after the first contents
  2555. ;; directive. Delete that region.
  2556. (goto-char (point-min))
  2557. ;; FIXME: Should accept indentation of the whole block.
  2558. ;; We look for the following and the following only (in other words, if
  2559. ;; your syntax differs, this won't work.).
  2560. ;;
  2561. ;; .. contents:: [...anything here...]
  2562. ;; [:field: value]...
  2563. ;; ..
  2564. ;; XXXXXXXX
  2565. ;; XXXXXXXX
  2566. ;; [more lines]
  2567. ;; FIXME: Works only for the first of these tocs. There should be a
  2568. ;; fixed text after the comment such as "RST-MODE ELECTRIC TOC".
  2569. ;; May be parameters such as `max-level' should be appended.
  2570. (let ((beg (re-search-forward
  2571. (1value
  2572. (rst-re "^" 'exm-sta "contents" 'dcl-tag ".*\n"
  2573. "\\(?:" 'hws-sta 'fld-tag ".*\n\\)*" 'exm-tag))
  2574. nil t))
  2575. fnd)
  2576. (when
  2577. (and beg
  2578. (rst-forward-line-looking-at
  2579. 1 'lin-end
  2580. #'(lambda (mtcd)
  2581. (unless mtcd
  2582. (rst-apply-indented-blocks
  2583. (point) (point-max) (current-indentation)
  2584. #'(lambda (count _in-first _in-sub in-super in-empty
  2585. _relind)
  2586. (cond
  2587. ((or (> count 1) in-super))
  2588. ((not in-empty)
  2589. (setq fnd (line-end-position))
  2590. nil)))))
  2591. t)))
  2592. (when fnd
  2593. (delete-region beg fnd))
  2594. (goto-char beg)
  2595. (insert "\n ")
  2596. ;; FIXME: Ignores an `max-level' given to the original
  2597. ;; `rst-toc-insert'. `max-level' could be rendered to the first
  2598. ;; line.
  2599. (rst-toc-insert)))))
  2600. ;; Note: always return nil, because this may be used as a hook.
  2601. nil)
  2602. ;; FIXME: Updating the toc on saving would be nice. However, this doesn't work
  2603. ;; correctly:
  2604. ;;
  2605. ;; (add-hook 'write-contents-hooks 'rst-toc-update-fun)
  2606. ;; (defun rst-toc-update-fun ()
  2607. ;; ;; Disable undo for the write file hook.
  2608. ;; (let ((buffer-undo-list t)) (rst-toc-update) ))
  2609. ;; Maintain an alias for compatibility.
  2610. (defalias 'rst-toc-insert-update 'rst-toc-update)
  2611. (defconst rst-toc-buffer-name "*Table of Contents*"
  2612. "Name of the Table of Contents buffer.")
  2613. (defvar-local rst-toc-mode-return-wincfg nil
  2614. "Window configuration to which to return when leaving the TOC.")
  2615. (defun rst-toc ()
  2616. ;; testcover: ok.
  2617. "Display a table of contents for current buffer.
  2618. Displays all section titles found in the current buffer in a
  2619. hierarchical list. The resulting buffer can be navigated, and
  2620. selecting a section title moves the cursor to that section."
  2621. (interactive)
  2622. (rst-reset-section-caches)
  2623. (let* ((wincfg (list (current-window-configuration) (point-marker)))
  2624. (sectree (rst-all-stn))
  2625. (target-stn (rst-stn-containing-point sectree))
  2626. (target-buf (current-buffer))
  2627. (buf (get-buffer-create rst-toc-buffer-name))
  2628. target-pos)
  2629. (with-current-buffer buf
  2630. (let ((inhibit-read-only t))
  2631. (rst-toc-mode)
  2632. (delete-region (point-min) (point-max))
  2633. ;; FIXME: Could use a customizable style.
  2634. (setq target-pos (rst-toc-insert-tree
  2635. sectree target-buf 'plain nil nil target-stn))))
  2636. (display-buffer buf)
  2637. (pop-to-buffer buf)
  2638. (setq rst-toc-mode-return-wincfg wincfg)
  2639. (goto-char (or target-pos (point-min)))))
  2640. ;; Maintain an alias for compatibility.
  2641. (defalias 'rst-goto-section 'rst-toc-follow-link)
  2642. (defun rst-toc-follow-link (link-buf link-pnt kill)
  2643. ;; testcover: ok.
  2644. "Follow the link to the section at LINK-PNT in LINK-BUF.
  2645. LINK-PNT and LINK-BUF default to the point in the current buffer.
  2646. With prefix argument KILL a TOC buffer is destroyed. Throw an
  2647. error if there is no working link at the given position."
  2648. (interactive "i\nd\nP")
  2649. (unless link-buf
  2650. (setq link-buf (current-buffer)))
  2651. ;; Do not catch errors from `rst-toc-get-link' because otherwise the error is
  2652. ;; suppressed and invisible in interactive use.
  2653. (let ((mrkr (rst-toc-get-link link-buf link-pnt)))
  2654. (condition-case nil
  2655. (rst-toc-mode-return kill)
  2656. ;; Catch errors when not in `toc-mode'.
  2657. (error nil))
  2658. (pop-to-buffer (marker-buffer mrkr))
  2659. (goto-char mrkr)
  2660. ;; FIXME: Should be a customizable number of lines from beginning or end of
  2661. ;; window just like the argument to `recenter`. It would be ideal if
  2662. ;; the adornment is always completely visible.
  2663. (recenter 5)))
  2664. ;; Maintain an alias for compatibility.
  2665. (defalias 'rst-toc-mode-goto-section 'rst-toc-mode-follow-link-kill)
  2666. ;; FIXME: Cursor before or behind the list must be handled properly; before the
  2667. ;; list should jump to the top and behind the list to the last normal
  2668. ;; paragraph.
  2669. (defun rst-toc-mode-follow-link-kill ()
  2670. ;; testcover: ok.
  2671. "Follow the link to the section at point and kill the TOC buffer."
  2672. (interactive)
  2673. (rst-toc-follow-link (current-buffer) (point) t))
  2674. ;; Maintain an alias for compatibility.
  2675. (defalias 'rst-toc-mode-mouse-goto 'rst-toc-mouse-follow-link)
  2676. (defun rst-toc-mouse-follow-link (event kill)
  2677. ;; testcover: uncovered.
  2678. "In `rst-toc' mode, go to the occurrence whose line you click on.
  2679. EVENT is the input event. Kill TOC buffer if KILL."
  2680. (interactive "e\ni")
  2681. (rst-toc-follow-link (window-buffer (posn-window (event-end event)))
  2682. (posn-point (event-end event)) kill))
  2683. ;; Maintain an alias for compatibility.
  2684. (defalias 'rst-toc-mode-mouse-goto-kill 'rst-toc-mode-mouse-follow-link-kill)
  2685. (defun rst-toc-mode-mouse-follow-link-kill (event)
  2686. ;; testcover: uncovered.
  2687. "Same as `rst-toc-mouse-follow-link', but kill TOC buffer as well.
  2688. EVENT is the input event."
  2689. (interactive "e")
  2690. (rst-toc-mouse-follow-link event t))
  2691. ;; Maintain an alias for compatibility.
  2692. (defalias 'rst-toc-quit-window 'rst-toc-mode-return)
  2693. (defun rst-toc-mode-return (kill)
  2694. ;; testcover: ok.
  2695. "Leave the current TOC buffer and return to the previous environment.
  2696. With prefix argument KILL non-nil, kill the buffer instead of
  2697. burying it."
  2698. (interactive "P")
  2699. (unless rst-toc-mode-return-wincfg
  2700. (error "Not in a `toc-mode' buffer"))
  2701. (cl-destructuring-bind
  2702. (wincfg pos
  2703. &aux (toc-buf (current-buffer)))
  2704. rst-toc-mode-return-wincfg
  2705. (set-window-configuration wincfg)
  2706. (goto-char pos)
  2707. (if kill
  2708. (kill-buffer toc-buf)
  2709. (bury-buffer toc-buf))))
  2710. (defun rst-toc-mode-return-kill ()
  2711. ;; testcover: uncovered.
  2712. "Like `rst-toc-mode-return' but kill TOC buffer."
  2713. (interactive)
  2714. (rst-toc-mode-return t))
  2715. (defvar rst-toc-mode-map
  2716. (let ((map (make-sparse-keymap)))
  2717. (define-key map [mouse-1] #'rst-toc-mode-mouse-follow-link-kill)
  2718. (define-key map [mouse-2] #'rst-toc-mouse-follow-link)
  2719. (define-key map "\C-m" #'rst-toc-mode-follow-link-kill)
  2720. (define-key map "f" #'rst-toc-mode-follow-link-kill)
  2721. (define-key map "n" #'next-line)
  2722. (define-key map "p" #'previous-line)
  2723. (define-key map "q" #'rst-toc-mode-return)
  2724. (define-key map "z" #'rst-toc-mode-return-kill)
  2725. map)
  2726. "Keymap for `rst-toc-mode'.")
  2727. (define-derived-mode rst-toc-mode special-mode "ReST-TOC"
  2728. "Major mode for output from \\[rst-toc], the table-of-contents for the document.
  2729. \\{rst-toc-mode-map}"
  2730. ;; FIXME: `revert-buffer-function` must be defined so `revert-buffer` works
  2731. ;; as expected for a special mode. In particular the referred buffer
  2732. ;; needs to be rescanned and the TOC must be updated accordingly.
  2733. ;; FIXME: Should contain the name of the buffer this is the toc of.
  2734. (setq header-line-format "Table of Contents"))
  2735. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2736. ;; Section movement
  2737. ;; FIXME testcover: Use `testcover'. Mark up a function with sufficient test
  2738. ;; coverage by a comment tagged with `testcover' after the
  2739. ;; `defun'. Then move this comment.
  2740. (defun rst-forward-section (offset)
  2741. "Jump forward OFFSET section titles ending up at the start of the title line.
  2742. OFFSET defaults to 1 and may be negative to move backward. An
  2743. OFFSET of 0 does not move unless point is inside a title. Go to
  2744. end or beginning of buffer if no more section titles in the desired
  2745. direction."
  2746. (interactive "p")
  2747. (rst-reset-section-caches)
  2748. (let* ((ttls (rst-all-ttls))
  2749. (count (length ttls))
  2750. (pnt (point))
  2751. (contained nil) ; Title contains point (or is after point otherwise).
  2752. (found (or (cl-position-if
  2753. ;; Find a title containing or after point.
  2754. #'(lambda (ttl)
  2755. (let ((cmp (rst-Ttl-contains ttl pnt)))
  2756. (cond
  2757. ((= cmp 0) ; Title contains point.
  2758. (setq contained t)
  2759. t)
  2760. ((> cmp 0) ; Title after point.
  2761. t))))
  2762. ttls)
  2763. ;; Point after all titles.
  2764. count))
  2765. (target (+ found offset
  2766. ;; If point is in plain text found title is already one
  2767. ;; step forward.
  2768. (if (and (not contained) (>= offset 0)) -1 0))))
  2769. (goto-char (cond
  2770. ((< target 0)
  2771. (point-min))
  2772. ((>= target count)
  2773. (point-max))
  2774. ((and (not contained) (= offset 0))
  2775. ;; Point not in title and should not move - do not move.
  2776. pnt)
  2777. ((rst-Ttl-get-title-beginning (nth target ttls)))))))
  2778. (defun rst-backward-section (offset)
  2779. "Like `rst-forward-section', except move backward by OFFSET."
  2780. (interactive "p")
  2781. (rst-forward-section (- offset)))
  2782. ;; FIXME: What is `allow-extend' for? See `mark-paragraph' for an explanation.
  2783. (defun rst-mark-section (&optional count allow-extend)
  2784. "Select COUNT sections around point.
  2785. Mark following sections for positive COUNT or preceding sections
  2786. for negative COUNT."
  2787. ;; Cloned from mark-paragraph.
  2788. (interactive "p\np")
  2789. (unless count (setq count 1))
  2790. (when (zerop count)
  2791. (error "Cannot mark zero sections"))
  2792. (cond ((and allow-extend
  2793. (or (and (eq last-command this-command) (mark t))
  2794. (use-region-p)))
  2795. (set-mark
  2796. (save-excursion
  2797. (goto-char (mark))
  2798. (rst-forward-section count)
  2799. (point))))
  2800. (t
  2801. (rst-forward-section count)
  2802. (push-mark nil t t)
  2803. (rst-forward-section (- count)))))
  2804. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2805. ;; Indentation
  2806. (defun rst-find-leftmost-column (beg end)
  2807. "Return the leftmost column spanned by region BEG to END.
  2808. The line containing the start of the region is always considered
  2809. spanned. If the region ends at the beginning of a line this line
  2810. is not considered spanned, otherwise it is spanned."
  2811. (let (mincol)
  2812. (save-match-data
  2813. (save-excursion
  2814. (goto-char beg)
  2815. (1value
  2816. (rst-forward-line-strict 0))
  2817. (while (< (point) end)
  2818. (unless (looking-at (rst-re 'lin-end))
  2819. (setq mincol (if mincol
  2820. (min mincol (current-indentation))
  2821. (current-indentation))))
  2822. (rst-forward-line-strict 1 end)))
  2823. mincol)))
  2824. ;; FIXME: At the moment only block comments with leading empty comment line are
  2825. ;; supported. Comment lines with leading comment markup should be also
  2826. ;; supported. May be a customizable option could control which style to
  2827. ;; prefer.
  2828. (defgroup rst-indent nil "Settings for indentation in reStructuredText.
  2829. In reStructuredText indentation points are usually determined by
  2830. preceding lines. Sometimes the syntax allows arbitrary indentation
  2831. points such as where to start the first line following a directive.
  2832. These indentation widths can be customized here."
  2833. :group 'rst
  2834. :package-version '(rst . "1.1.0"))
  2835. (define-obsolete-variable-alias
  2836. 'rst-shift-basic-offset 'rst-indent-width "rst 1.0.0")
  2837. (defcustom rst-indent-width 2
  2838. "Indentation when there is no more indentation point given."
  2839. :group 'rst-indent
  2840. :type '(integer))
  2841. (rst-testcover-defcustom)
  2842. (defcustom rst-indent-field 3
  2843. "Indentation for first line after a field or 0 to always indent for content."
  2844. :group 'rst-indent
  2845. :package-version '(rst . "1.1.0")
  2846. :type '(integer))
  2847. (rst-testcover-defcustom)
  2848. (defcustom rst-indent-literal-normal 3
  2849. "Default indentation for literal block after a markup on an own line."
  2850. :group 'rst-indent
  2851. :package-version '(rst . "1.1.0")
  2852. :type '(integer))
  2853. (rst-testcover-defcustom)
  2854. (defcustom rst-indent-literal-minimized 2
  2855. "Default indentation for literal block after a minimized markup."
  2856. :group 'rst-indent
  2857. :package-version '(rst . "1.1.0")
  2858. :type '(integer))
  2859. (rst-testcover-defcustom)
  2860. (defcustom rst-indent-comment 3
  2861. "Default indentation for first line of a comment."
  2862. :group 'rst-indent
  2863. :package-version '(rst . "1.1.0")
  2864. :type '(integer))
  2865. (rst-testcover-defcustom)
  2866. ;; FIXME: Must consider other tabs:
  2867. ;; * Line blocks
  2868. ;; * Definition lists
  2869. ;; * Option lists
  2870. (defun rst-line-tabs ()
  2871. "Return tabs of the current line or nil for no tab.
  2872. The list is sorted so the tab where writing continues most likely
  2873. is the first one. Each tab is of the form (COLUMN . INNER).
  2874. COLUMN is the column of the tab. INNER is non-nil if this is an
  2875. inner tab. I.e. a tab which does come from the basic indentation
  2876. and not from inner alignment points."
  2877. (save-excursion
  2878. (rst-forward-line-strict 0)
  2879. (save-match-data
  2880. (unless (looking-at (rst-re 'lin-end))
  2881. (back-to-indentation)
  2882. ;; Current indentation is always the least likely tab.
  2883. (let ((tabs (list (list (point) 0 nil)))) ; (POINT OFFSET INNER)
  2884. ;; Push inner tabs more likely to continue writing.
  2885. (cond
  2886. ;; Item.
  2887. ((looking-at (rst-re '(:grp itmany-tag hws-sta) '(:grp "\\S ") "?"))
  2888. (when (match-string 2)
  2889. (push (list (match-beginning 2) 0 t) tabs)))
  2890. ;; Field.
  2891. ((looking-at (rst-re '(:grp fld-tag) '(:grp hws-tag)
  2892. '(:grp "\\S ") "?"))
  2893. (unless (zerop rst-indent-field)
  2894. (push (list (match-beginning 1) rst-indent-field t) tabs))
  2895. (if (match-string 3)
  2896. (push (list (match-beginning 3) 0 t) tabs)
  2897. (if (zerop rst-indent-field)
  2898. (push (list (match-end 2)
  2899. (if (string= (match-string 2) "") 1 0)
  2900. t)
  2901. tabs))))
  2902. ;; Directive.
  2903. ((looking-at (rst-re 'dir-sta-3 '(:grp "\\S ") "?"))
  2904. (push (list (match-end 1) 0 t) tabs)
  2905. (unless (string= (match-string 2) "")
  2906. (push (list (match-end 2) 0 t) tabs))
  2907. (when (match-string 4)
  2908. (push (list (match-beginning 4) 0 t) tabs)))
  2909. ;; Footnote or citation definition.
  2910. ((looking-at (rst-re 'fnc-sta-2 '(:grp "\\S ") "?"))
  2911. (push (list (match-end 1) 0 t) tabs)
  2912. (when (match-string 3)
  2913. (push (list (match-beginning 3) 0 t) tabs)))
  2914. ;; Comment.
  2915. ((looking-at (rst-re 'cmt-sta-1))
  2916. (push (list (point) rst-indent-comment t) tabs)))
  2917. ;; Start of literal block.
  2918. (when (looking-at (rst-re 'lit-sta-2))
  2919. (cl-destructuring-bind (point offset _inner) (car tabs)
  2920. (push (list point
  2921. (+ offset
  2922. (if (match-string 1)
  2923. rst-indent-literal-minimized
  2924. rst-indent-literal-normal))
  2925. t)
  2926. tabs)))
  2927. (mapcar (cl-function
  2928. (lambda ((point offset inner))
  2929. (goto-char point)
  2930. (cons (+ (current-column) offset) inner)))
  2931. tabs))))))
  2932. (defun rst-compute-tabs (pt)
  2933. "Build the list of possible tabs for all lines above.
  2934. Search backwards from point PT to build the list of possible tabs.
  2935. Return a list of tabs sorted by likeliness to continue writing
  2936. like `rst-line-tabs'. Nearer lines have generally a higher
  2937. likeliness than farther lines. Return nil if no tab is found in
  2938. the text above."
  2939. ;; FIXME: See test `indent-for-tab-command-BUGS`.
  2940. (save-excursion
  2941. (goto-char pt)
  2942. (let (leftmost ; Leftmost column found so far.
  2943. innermost ; Leftmost column for inner tab.
  2944. tablist)
  2945. (while (and (rst-forward-line-strict -1)
  2946. (or (not leftmost)
  2947. (> leftmost 0)))
  2948. (let ((tabs (rst-line-tabs)))
  2949. (when tabs
  2950. (let ((leftcol (apply #'min (mapcar #'car tabs))))
  2951. ;; Consider only lines indented less or same if not INNERMOST.
  2952. (when (or (not leftmost)
  2953. (< leftcol leftmost)
  2954. (and (not innermost) (= leftcol leftmost)))
  2955. (rst-destructuring-dolist ((column &rest inner) tabs)
  2956. (when (or
  2957. (and (not inner)
  2958. (or (not leftmost)
  2959. (< column leftmost)))
  2960. (and inner
  2961. (or (not innermost)
  2962. (< column innermost))))
  2963. (setq tablist (cl-adjoin column tablist))))
  2964. (setq innermost (if (cl-some #'cdr tabs) ; Has inner.
  2965. leftcol
  2966. innermost))
  2967. (setq leftmost leftcol))))))
  2968. (nreverse tablist))))
  2969. (defun rst-indent-line (&optional dflt)
  2970. "Indent current line to next best reStructuredText tab.
  2971. The next best tab is taken from the tab list returned by
  2972. `rst-compute-tabs' which is used in a cyclic manner. If the
  2973. current indentation does not end on a tab use the first one. If
  2974. the current indentation is on a tab use the next tab. This allows
  2975. a repeated use of \\[indent-for-tab-command] to cycle through all
  2976. possible tabs. If no indentation is possible return `noindent' or
  2977. use DFLT. Return the indentation indented to. When point is in
  2978. indentation it ends up at its end. Otherwise the point is kept
  2979. relative to the content."
  2980. (let* ((pt (point-marker))
  2981. (cur (current-indentation))
  2982. (clm (current-column))
  2983. (tabs (rst-compute-tabs (point)))
  2984. (fnd (cl-position cur tabs :test #'equal))
  2985. ind)
  2986. (if (and (not tabs) (not dflt))
  2987. 'noindent
  2988. (if (not tabs)
  2989. (setq ind dflt)
  2990. (if (not fnd)
  2991. (setq fnd 0)
  2992. (setq fnd (1+ fnd))
  2993. (if (>= fnd (length tabs))
  2994. (setq fnd 0)))
  2995. (setq ind (nth fnd tabs)))
  2996. (indent-line-to ind)
  2997. (if (> clm cur)
  2998. (goto-char pt))
  2999. (set-marker pt nil)
  3000. ind)))
  3001. (defun rst-shift-region (beg end cnt)
  3002. "Shift region BEG to END by CNT tabs.
  3003. Shift by one tab to the right (CNT > 0) or left (CNT < 0) or
  3004. remove all indentation (CNT = 0). A tab is taken from the text
  3005. above. If no suitable tab is found `rst-indent-width' is used."
  3006. (interactive "r\np")
  3007. (let ((tabs (sort (rst-compute-tabs beg)
  3008. #'(lambda (x y)
  3009. (<= x y))))
  3010. (leftmostcol (rst-find-leftmost-column beg end)))
  3011. (when (or (> leftmostcol 0) (> cnt 0))
  3012. ;; Apply the indent.
  3013. (indent-rigidly
  3014. beg end
  3015. (if (zerop cnt)
  3016. (- leftmostcol)
  3017. ;; Find the next tab after the leftmost column.
  3018. (let* ((cmp (if (> cnt 0) #'> #'<))
  3019. (tabs (if (> cnt 0) tabs (reverse tabs)))
  3020. (len (length tabs))
  3021. (dir (cl-signum cnt)) ; Direction to take.
  3022. (abs (abs cnt)) ; Absolute number of steps to take.
  3023. ;; Get the position of the first tab beyond leftmostcol.
  3024. (fnd (cl-position-if #'(lambda (elt)
  3025. (funcall cmp elt leftmostcol))
  3026. tabs))
  3027. ;; Virtual position of tab.
  3028. (pos (+ (or fnd len) (1- abs)))
  3029. (tab (if (< pos len)
  3030. ;; Tab exists - use it.
  3031. (nth pos tabs)
  3032. ;; Column needs to be computed.
  3033. (let ((col (+ (or (car (last tabs)) leftmostcol)
  3034. ;; Base on last known column.
  3035. (* (- pos (1- len)) ; Distance left.
  3036. dir ; Direction to take.
  3037. rst-indent-width))))
  3038. (if (< col 0) 0 col)))))
  3039. (- tab leftmostcol)))))))
  3040. ;; FIXME: A paragraph with an (incorrectly) indented second line is not filled
  3041. ;; correctly::
  3042. ;;
  3043. ;; Some start
  3044. ;; continued wrong
  3045. (defun rst-adaptive-fill ()
  3046. "Return fill prefix found at point.
  3047. Value for `adaptive-fill-function'."
  3048. (save-match-data
  3049. (let ((fnd (if (looking-at adaptive-fill-regexp)
  3050. (match-string-no-properties 0))))
  3051. (if (save-match-data
  3052. (not (string-match comment-start-skip fnd)))
  3053. ;; An non-comment prefix is fine.
  3054. fnd
  3055. ;; Matches a comment - return whitespace instead.
  3056. (make-string (-
  3057. (save-excursion
  3058. (goto-char (match-end 0))
  3059. (current-column))
  3060. (save-excursion
  3061. (goto-char (match-beginning 0))
  3062. (current-column))) ? )))))
  3063. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3064. ;; Comments
  3065. (defun rst-comment-line-break (&optional soft)
  3066. "Break line and indent, continuing reStructuredText comment if within one.
  3067. Value for `comment-line-break-function'. If SOFT use soft
  3068. newlines as mandated by `comment-line-break-function'."
  3069. (if soft
  3070. (insert-and-inherit ?\n)
  3071. (newline 1))
  3072. (save-excursion
  3073. (forward-char -1)
  3074. (delete-horizontal-space))
  3075. (delete-horizontal-space)
  3076. (let ((tabs (rst-compute-tabs (point))))
  3077. (when tabs
  3078. (indent-line-to (car tabs)))))
  3079. (defun rst-comment-indent ()
  3080. "Return indentation for current comment line."
  3081. (car (rst-compute-tabs (point))))
  3082. (defun rst-comment-insert-comment ()
  3083. "Insert a comment in the current line."
  3084. (rst-indent-line 0)
  3085. (insert comment-start))
  3086. (defun rst-comment-region (beg end &optional arg)
  3087. "Comment or uncomment the current region.
  3088. Region is from BEG to END. Uncomment if ARG."
  3089. (save-excursion
  3090. (if (consp arg)
  3091. (rst-uncomment-region beg end arg)
  3092. (goto-char beg)
  3093. (rst-forward-line-strict 0)
  3094. (let ((ind (current-indentation))
  3095. (bol (point)))
  3096. (indent-rigidly bol end rst-indent-comment)
  3097. (goto-char bol)
  3098. (open-line 1)
  3099. (indent-line-to ind)
  3100. (insert (comment-string-strip comment-start t t))))))
  3101. (defun rst-uncomment-region (beg end &optional _arg)
  3102. "Uncomment the current region.
  3103. Region is from BEG to END. _ARG is ignored"
  3104. (save-excursion
  3105. (goto-char beg)
  3106. (rst-forward-line-strict 0)
  3107. (let ((bol (point)))
  3108. (rst-forward-line-strict 1 end)
  3109. (indent-rigidly (point) end (- rst-indent-comment))
  3110. (goto-char bol)
  3111. (rst-delete-entire-line 0))))
  3112. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3113. ;; Apply to indented block
  3114. ;; FIXME: These next functions should become part of a larger effort to redo
  3115. ;; the bullets in bulleted lists. The enumerate would just be one of
  3116. ;; the possible outputs.
  3117. ;;
  3118. ;; FIXME: We need to do the enumeration removal as well.
  3119. (defun rst-apply-indented-blocks (beg end ind fun)
  3120. "Apply FUN to all lines from BEG to END in blocks indented to IND.
  3121. The first indented block starts with the first non-empty line
  3122. containing or after BEG and indented to IND. After the first
  3123. line the indented block may contain more lines with same
  3124. indentation (the paragraph) followed by empty lines and lines
  3125. more indented (the sub-blocks). A following line indented to IND
  3126. starts the next paragraph. A non-empty line with less
  3127. indentation than IND terminates the current paragraph. FUN is
  3128. applied to each line like this
  3129. (FUN COUNT IN-FIRST IN-SUB IN-SUPER IN-EMPTY RELIND)
  3130. COUNT is 0 before the first paragraph and increments for every
  3131. paragraph found on level IND. IN-FIRST is non-nil if this is the
  3132. first line of such a paragraph. IN-SUB is non-nil if this line
  3133. is part of a sub-block while IN-SUPER is non-nil of this line is
  3134. part of a less indented block (super-block). IN-EMPTY is non-nil
  3135. if this line is empty where an empty line is considered being
  3136. part of the previous block. RELIND is nil for an empty line, 0
  3137. for a line indented to IND, and the positive or negative number
  3138. of columns more or less indented otherwise. When FUN is called
  3139. point is immediately behind indentation of that line. FUN may
  3140. change everything as long as a marker at END and at the beginning
  3141. of the following line is handled correctly by the change. A
  3142. non-nil return value from FUN breaks the loop and is returned.
  3143. Otherwise return nil."
  3144. (let ((endm (copy-marker end t))
  3145. (count 0) ; Before first indented block.
  3146. (nxt (when (< beg end)
  3147. (copy-marker beg t)))
  3148. (broken t)
  3149. in-sub in-super stop)
  3150. (save-match-data
  3151. (save-excursion
  3152. (while (and (not stop) nxt)
  3153. (set-marker
  3154. (goto-char nxt) nil)
  3155. (setq nxt (save-excursion
  3156. ;; FIXME refactoring: Replace `(forward-line)
  3157. ;; (back-to-indentation)` by
  3158. ;; `(forward-to-indentation)`
  3159. (when (and (rst-forward-line-strict 1 endm)
  3160. (< (point) endm))
  3161. (copy-marker (point) t))))
  3162. (back-to-indentation)
  3163. (let ((relind (- (current-indentation) ind))
  3164. (in-empty (looking-at (rst-re 'lin-end)))
  3165. in-first)
  3166. (cond
  3167. (in-empty
  3168. (setq relind nil))
  3169. ((< relind 0)
  3170. (setq in-sub nil)
  3171. (setq in-super t))
  3172. ((> relind 0)
  3173. (setq in-sub t)
  3174. (setq in-super nil))
  3175. (t ; Non-empty line in indented block.
  3176. (when (or broken in-sub in-super)
  3177. (setq in-first t)
  3178. (cl-incf count))
  3179. (setq in-sub nil)
  3180. (setq in-super nil)))
  3181. (save-excursion
  3182. (setq
  3183. stop
  3184. (funcall fun count in-first in-sub in-super in-empty relind)))
  3185. (setq broken in-empty)))
  3186. (set-marker endm nil)
  3187. stop))))
  3188. (defun rst-enumerate-region (beg end all)
  3189. "Add enumeration to all the leftmost paragraphs in the given region.
  3190. The region is specified between BEG and END. With ALL,
  3191. do all lines instead of just paragraphs."
  3192. (interactive "r\nP")
  3193. (let ((enum 0)
  3194. (indent ""))
  3195. (rst-apply-indented-blocks
  3196. beg end (rst-find-leftmost-column beg end)
  3197. #'(lambda (count in-first in-sub in-super in-empty _relind)
  3198. (cond
  3199. (in-empty)
  3200. (in-super)
  3201. ((zerop count))
  3202. (in-sub
  3203. (insert indent))
  3204. ((or in-first all)
  3205. (let ((tag (format "%d. " (cl-incf enum))))
  3206. (setq indent (make-string (length tag) ? ))
  3207. (insert tag)))
  3208. (t
  3209. (insert indent)))
  3210. nil))))
  3211. ;; FIXME: Does not deal with deeper indentation - although
  3212. ;; `rst-apply-indented-blocks' could.
  3213. (defun rst-bullet-list-region (beg end all)
  3214. "Add bullets to all the leftmost paragraphs in the given region.
  3215. The region is specified between BEG and END. With ALL,
  3216. do all lines instead of just paragraphs."
  3217. (interactive "r\nP")
  3218. (unless rst-preferred-bullets
  3219. (error "No preferred bullets defined"))
  3220. (let* ((bul (format "%c " (car rst-preferred-bullets)))
  3221. (indent (make-string (length bul) ? )))
  3222. (rst-apply-indented-blocks
  3223. beg end (rst-find-leftmost-column beg end)
  3224. #'(lambda (count in-first in-sub in-super in-empty _relind)
  3225. (cond
  3226. (in-empty)
  3227. (in-super)
  3228. ((zerop count))
  3229. (in-sub
  3230. (insert indent))
  3231. ((or in-first all)
  3232. (insert bul))
  3233. (t
  3234. (insert indent)))
  3235. nil))))
  3236. ;; FIXME: Does not deal with a varying number of digits appropriately.
  3237. ;; FIXME: Does not deal with multiple levels independently.
  3238. ;; FIXME: Does not indent a multiline item correctly.
  3239. (defun rst-convert-bullets-to-enumeration (beg end)
  3240. "Convert the bulleted and enumerated items in the region to enumerated lists.
  3241. Renumber as necessary. Region is from BEG to END."
  3242. (interactive "r")
  3243. (let ((count 1))
  3244. (save-match-data
  3245. (save-excursion
  3246. (dolist (marker (mapcar
  3247. (cl-function
  3248. (lambda ((pnt &rest clm))
  3249. (copy-marker pnt)))
  3250. (rst-find-begs beg end 'itmany-beg-1)))
  3251. (set-marker
  3252. (goto-char marker) nil)
  3253. (looking-at (rst-re 'itmany-beg-1))
  3254. (replace-match (format "%d." count) nil nil nil 1)
  3255. (cl-incf count))))))
  3256. (defun rst-line-block-region (beg end &optional with-empty)
  3257. "Add line block prefixes for a region.
  3258. Region is from BEG to END. With WITH-EMPTY prefix empty lines too."
  3259. (interactive "r\nP")
  3260. (let ((ind (rst-find-leftmost-column beg end)))
  3261. (rst-apply-indented-blocks
  3262. beg end ind
  3263. #'(lambda (_count _in-first _in-sub in-super in-empty _relind)
  3264. (when (and (not in-super) (or with-empty (not in-empty)))
  3265. (move-to-column ind t)
  3266. (insert "| "))
  3267. nil))))
  3268. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3269. ;; Font lock
  3270. (require 'font-lock)
  3271. ;; FIXME: The obsolete variables need to disappear.
  3272. ;; The following versions have been done inside Emacs and should not be
  3273. ;; replaced by `:package-version' attributes until a change.
  3274. (defgroup rst-faces nil "Faces used in Rst Mode."
  3275. :group 'rst
  3276. :group 'faces
  3277. :version "21.1")
  3278. (defface rst-block '((t :inherit font-lock-keyword-face))
  3279. "Face used for all syntax marking up a special block."
  3280. :version "24.1"
  3281. :group 'rst-faces)
  3282. (defcustom rst-block-face 'rst-block
  3283. "All syntax marking up a special block."
  3284. :version "24.1"
  3285. :group 'rst-faces
  3286. :type '(face))
  3287. (rst-testcover-defcustom)
  3288. (make-obsolete-variable 'rst-block-face
  3289. "customize the face `rst-block' instead."
  3290. "24.1")
  3291. (defface rst-external '((t :inherit font-lock-type-face))
  3292. "Face used for field names and interpreted text."
  3293. :version "24.1"
  3294. :group 'rst-faces)
  3295. (defcustom rst-external-face 'rst-external
  3296. "Field names and interpreted text."
  3297. :version "24.1"
  3298. :group 'rst-faces
  3299. :type '(face))
  3300. (rst-testcover-defcustom)
  3301. (make-obsolete-variable 'rst-external-face
  3302. "customize the face `rst-external' instead."
  3303. "24.1")
  3304. (defface rst-definition '((t :inherit font-lock-function-name-face))
  3305. "Face used for all other defining constructs."
  3306. :version "24.1"
  3307. :group 'rst-faces)
  3308. (defcustom rst-definition-face 'rst-definition
  3309. "All other defining constructs."
  3310. :version "24.1"
  3311. :group 'rst-faces
  3312. :type '(face))
  3313. (rst-testcover-defcustom)
  3314. (make-obsolete-variable 'rst-definition-face
  3315. "customize the face `rst-definition' instead."
  3316. "24.1")
  3317. ;; XEmacs compatibility (?).
  3318. (defface rst-directive (if (boundp 'font-lock-builtin-face)
  3319. '((t :inherit font-lock-builtin-face))
  3320. '((t :inherit font-lock-preprocessor-face)))
  3321. "Face used for directives and roles."
  3322. :version "24.1"
  3323. :group 'rst-faces)
  3324. (defcustom rst-directive-face 'rst-directive
  3325. "Directives and roles."
  3326. :group 'rst-faces
  3327. :type '(face))
  3328. (rst-testcover-defcustom)
  3329. (make-obsolete-variable 'rst-directive-face
  3330. "customize the face `rst-directive' instead."
  3331. "24.1")
  3332. (defface rst-comment '((t :inherit font-lock-comment-face))
  3333. "Face used for comments."
  3334. :version "24.1"
  3335. :group 'rst-faces)
  3336. (defcustom rst-comment-face 'rst-comment
  3337. "Comments."
  3338. :version "24.1"
  3339. :group 'rst-faces
  3340. :type '(face))
  3341. (rst-testcover-defcustom)
  3342. (make-obsolete-variable 'rst-comment-face
  3343. "customize the face `rst-comment' instead."
  3344. "24.1")
  3345. (defface rst-emphasis1 '((t :inherit italic))
  3346. "Face used for simple emphasis."
  3347. :version "24.1"
  3348. :group 'rst-faces)
  3349. (defcustom rst-emphasis1-face 'rst-emphasis1
  3350. "Simple emphasis."
  3351. :version "24.1"
  3352. :group 'rst-faces
  3353. :type '(face))
  3354. (rst-testcover-defcustom)
  3355. (make-obsolete-variable 'rst-emphasis1-face
  3356. "customize the face `rst-emphasis1' instead."
  3357. "24.1")
  3358. (defface rst-emphasis2 '((t :inherit bold))
  3359. "Face used for double emphasis."
  3360. :version "24.1"
  3361. :group 'rst-faces)
  3362. (defcustom rst-emphasis2-face 'rst-emphasis2
  3363. "Double emphasis."
  3364. :group 'rst-faces
  3365. :type '(face))
  3366. (rst-testcover-defcustom)
  3367. (make-obsolete-variable 'rst-emphasis2-face
  3368. "customize the face `rst-emphasis2' instead."
  3369. "24.1")
  3370. (defface rst-literal '((t :inherit font-lock-string-face))
  3371. "Face used for literal text."
  3372. :version "24.1"
  3373. :group 'rst-faces)
  3374. (defcustom rst-literal-face 'rst-literal
  3375. "Literal text."
  3376. :version "24.1"
  3377. :group 'rst-faces
  3378. :type '(face))
  3379. (rst-testcover-defcustom)
  3380. (make-obsolete-variable 'rst-literal-face
  3381. "customize the face `rst-literal' instead."
  3382. "24.1")
  3383. (defface rst-reference '((t :inherit font-lock-variable-name-face))
  3384. "Face used for references to a definition."
  3385. :version "24.1"
  3386. :group 'rst-faces)
  3387. (defcustom rst-reference-face 'rst-reference
  3388. "References to a definition."
  3389. :version "24.1"
  3390. :group 'rst-faces
  3391. :type '(face))
  3392. (rst-testcover-defcustom)
  3393. (make-obsolete-variable 'rst-reference-face
  3394. "customize the face `rst-reference' instead."
  3395. "24.1")
  3396. (defface rst-transition '((t :inherit font-lock-keyword-face))
  3397. "Face used for a transition."
  3398. :package-version '(rst . "1.3.0")
  3399. :group 'rst-faces)
  3400. (defface rst-adornment '((t :inherit font-lock-keyword-face))
  3401. "Face used for the adornment of a section header."
  3402. :package-version '(rst . "1.3.0")
  3403. :group 'rst-faces)
  3404. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3405. (dolist (var '(rst-level-face-max rst-level-face-base-color
  3406. rst-level-face-base-light
  3407. rst-level-face-format-light
  3408. rst-level-face-step-light
  3409. rst-level-1-face
  3410. rst-level-2-face
  3411. rst-level-3-face
  3412. rst-level-4-face
  3413. rst-level-5-face
  3414. rst-level-6-face))
  3415. (make-obsolete-variable var "customize the faces `rst-level-*' instead."
  3416. "24.3"))
  3417. ;; Define faces for the first 6 levels. More levels are possible, however.
  3418. (defface rst-level-1 '((((background light)) (:background "grey85"))
  3419. (((background dark)) (:background "grey15")))
  3420. "Default face for section title text at level 1."
  3421. :package-version '(rst . "1.4.0"))
  3422. (defface rst-level-2 '((((background light)) (:background "grey78"))
  3423. (((background dark)) (:background "grey22")))
  3424. "Default face for section title text at level 2."
  3425. :package-version '(rst . "1.4.0"))
  3426. (defface rst-level-3 '((((background light)) (:background "grey71"))
  3427. (((background dark)) (:background "grey29")))
  3428. "Default face for section title text at level 3."
  3429. :package-version '(rst . "1.4.0"))
  3430. (defface rst-level-4 '((((background light)) (:background "grey64"))
  3431. (((background dark)) (:background "grey36")))
  3432. "Default face for section title text at level 4."
  3433. :package-version '(rst . "1.4.0"))
  3434. (defface rst-level-5 '((((background light)) (:background "grey57"))
  3435. (((background dark)) (:background "grey43")))
  3436. "Default face for section title text at level 5."
  3437. :package-version '(rst . "1.4.0"))
  3438. (defface rst-level-6 '((((background light)) (:background "grey50"))
  3439. (((background dark)) (:background "grey50")))
  3440. "Default face for section title text at level 6."
  3441. :package-version '(rst . "1.4.0"))
  3442. (defcustom rst-adornment-faces-alist
  3443. '((t . rst-transition)
  3444. (nil . rst-adornment)
  3445. (1 . rst-level-1)
  3446. (2 . rst-level-2)
  3447. (3 . rst-level-3)
  3448. (4 . rst-level-4)
  3449. (5 . rst-level-5)
  3450. (6 . rst-level-6))
  3451. "Faces for the various adornment types.
  3452. Key is a number (for the section title text of that level
  3453. starting with 1), t (for transitions) or nil (for section title
  3454. adornment). If you need levels beyond 6 you have to define faces
  3455. of your own."
  3456. :group 'rst-faces
  3457. :type '(alist
  3458. :key-type
  3459. (choice
  3460. (integer :tag "Section level")
  3461. (const :tag "transitions" t)
  3462. (const :tag "section title adornment" nil))
  3463. :value-type (face)))
  3464. (rst-testcover-defcustom)
  3465. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3466. (defvar rst-font-lock-keywords
  3467. ;; The reST-links in the comments below all relate to sections in
  3468. ;; http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html.
  3469. `(;; FIXME: Block markup is not recognized in blocks after explicit markup
  3470. ;; start.
  3471. ;; Simple `Body Elements`_
  3472. ;; `Bullet Lists`_
  3473. ;; FIXME: A bullet directly after a field name is not recognized.
  3474. (,(rst-re 'lin-beg '(:grp bul-sta))
  3475. 1 rst-block-face)
  3476. ;; `Enumerated Lists`_
  3477. (,(rst-re 'lin-beg '(:grp enmany-sta))
  3478. 1 rst-block-face)
  3479. ;; `Definition Lists`_
  3480. ;; FIXME: missing.
  3481. ;; `Field Lists`_
  3482. (,(rst-re 'lin-beg '(:grp fld-tag) 'bli-sfx)
  3483. 1 rst-external-face)
  3484. ;; `Option Lists`_
  3485. (,(rst-re 'lin-beg '(:grp opt-tag (:shy optsep-tag opt-tag) "*")
  3486. '(:alt "$" (:seq hws-prt "\\{2\\}")))
  3487. 1 rst-block-face)
  3488. ;; `Line Blocks`_
  3489. ;; Only for lines containing no more bar - to distinguish from tables.
  3490. (,(rst-re 'lin-beg '(:grp "|" bli-sfx) "[^|\n]*$")
  3491. 1 rst-block-face)
  3492. ;; `Tables`_
  3493. ;; FIXME: missing
  3494. ;; All the `Explicit Markup Blocks`_
  3495. ;; `Footnotes`_ / `Citations`_
  3496. (,(rst-re 'lin-beg 'fnc-sta-2)
  3497. (1 rst-definition-face)
  3498. (2 rst-definition-face))
  3499. ;; `Directives`_ / `Substitution Definitions`_
  3500. (,(rst-re 'lin-beg 'dir-sta-3)
  3501. (1 rst-directive-face)
  3502. (2 rst-definition-face)
  3503. (3 rst-directive-face))
  3504. ;; `Hyperlink Targets`_
  3505. (,(rst-re 'lin-beg
  3506. '(:grp exm-sta "_" (:alt
  3507. (:seq "`" ilcbkqdef-tag "`")
  3508. (:seq (:alt "[^:\\\n]" "\\\\.") "+")) ":")
  3509. 'bli-sfx)
  3510. 1 rst-definition-face)
  3511. (,(rst-re 'lin-beg '(:grp "__") 'bli-sfx)
  3512. 1 rst-definition-face)
  3513. ;; All `Inline Markup`_
  3514. ;; Most of them may be multiline though this is uninteresting.
  3515. ;; FIXME: Condition 5 preventing fontification of e.g. "*" not implemented
  3516. ;; `Strong Emphasis`_.
  3517. (,(rst-re 'ilm-pfx '(:grp "\\*\\*" ilcast-tag "\\*\\*") 'ilm-sfx)
  3518. 1 rst-emphasis2-face)
  3519. ;; `Emphasis`_
  3520. (,(rst-re 'ilm-pfx '(:grp "\\*" ilcast-tag "\\*") 'ilm-sfx)
  3521. 1 rst-emphasis1-face)
  3522. ;; `Inline Literals`_
  3523. (,(rst-re 'ilm-pfx '(:grp "``" ilcbkq-tag "``") 'ilm-sfx)
  3524. 1 rst-literal-face)
  3525. ;; `Inline Internal Targets`_
  3526. (,(rst-re 'ilm-pfx '(:grp "_`" ilcbkq-tag "`") 'ilm-sfx)
  3527. 1 rst-definition-face)
  3528. ;; `Hyperlink References`_
  3529. ;; FIXME: `Embedded URIs and Aliases`_ not considered.
  3530. ;; FIXME: Directly adjacent marked up words are not fontified correctly
  3531. ;; unless they are not separated by two spaces: foo_ bar_.
  3532. (,(rst-re 'ilm-pfx '(:grp (:alt (:seq "`" ilcbkq-tag "`")
  3533. (:seq "\\sw" (:alt "\\sw" "-") "+\\sw"))
  3534. "__?") 'ilm-sfx)
  3535. 1 rst-reference-face)
  3536. ;; `Interpreted Text`_
  3537. (,(rst-re 'ilm-pfx '(:grp (:shy ":" sym-tag ":") "?")
  3538. '(:grp "`" ilcbkq-tag "`")
  3539. '(:grp (:shy ":" sym-tag ":") "?") 'ilm-sfx)
  3540. (1 rst-directive-face)
  3541. (2 rst-external-face)
  3542. (3 rst-directive-face))
  3543. ;; `Footnote References`_ / `Citation References`_
  3544. (,(rst-re 'ilm-pfx '(:grp fnc-tag "_") 'ilm-sfx)
  3545. 1 rst-reference-face)
  3546. ;; `Substitution References`_
  3547. ;; FIXME: References substitutions like |this|_ or |this|__ are not
  3548. ;; fontified correctly.
  3549. (,(rst-re 'ilm-pfx '(:grp sub-tag) 'ilm-sfx)
  3550. 1 rst-reference-face)
  3551. ;; `Standalone Hyperlinks`_
  3552. ;; FIXME: This takes it easy by using a whitespace as delimiter.
  3553. (,(rst-re 'ilm-pfx '(:grp uri-tag ":\\S +") 'ilm-sfx)
  3554. 1 rst-definition-face)
  3555. (,(rst-re 'ilm-pfx '(:grp sym-tag "@" sym-tag ) 'ilm-sfx)
  3556. 1 rst-definition-face)
  3557. ;; Do all block fontification as late as possible so 'append works.
  3558. ;; Sections_ / Transitions_
  3559. ;; For sections this is multiline.
  3560. (,(rst-re 'ado-beg-2-1)
  3561. (rst-font-lock-handle-adornment-matcher
  3562. (rst-font-lock-handle-adornment-pre-match-form
  3563. (match-string-no-properties 1) (match-end 1))
  3564. nil
  3565. (1 (cdr (assoc nil rst-adornment-faces-alist)) append t)
  3566. (2 (cdr (assoc rst-font-lock-adornment-level
  3567. rst-adornment-faces-alist)) append t)
  3568. (3 (cdr (assoc nil rst-adornment-faces-alist)) append t)))
  3569. ;; FIXME: FACESPEC could be used instead of ordinary faces to set
  3570. ;; properties on comments and literal blocks so they are *not*
  3571. ;; inline fontified. See (elisp)Search-based Fontification.
  3572. ;; FIXME: And / or use `syntax-propertize' functions as in `octave-mod.el'
  3573. ;; and other V24 modes. May make `font-lock-extend-region'
  3574. ;; superfluous.
  3575. ;; `Comments`_
  3576. ;; This is multiline.
  3577. (,(rst-re 'lin-beg 'cmt-sta-1)
  3578. (1 rst-comment-face)
  3579. (rst-font-lock-find-unindented-line-match
  3580. (rst-font-lock-find-unindented-line-limit (match-end 1))
  3581. nil
  3582. (0 rst-comment-face append)))
  3583. (,(rst-re 'lin-beg '(:grp exm-tag) '(:grp hws-tag) "$")
  3584. (1 rst-comment-face)
  3585. (2 rst-comment-face)
  3586. (rst-font-lock-find-unindented-line-match
  3587. (rst-font-lock-find-unindented-line-limit 'next)
  3588. nil
  3589. (0 rst-comment-face append)))
  3590. ;; FIXME: This is not rendered as comment::
  3591. ;; .. .. list-table::
  3592. ;; :stub-columns: 1
  3593. ;; :header-rows: 1
  3594. ;; FIXME: This is rendered wrong::
  3595. ;;
  3596. ;; xxx yyy::
  3597. ;;
  3598. ;; ----|> KKKKK <|----
  3599. ;; / \
  3600. ;; -|> AAAAAAAAAAPPPPPP <|- -|> AAAAAAAAAABBBBBBB <|-
  3601. ;; | | | |
  3602. ;; | | | |
  3603. ;; PPPPPP PPPPPPDDDDDDD BBBBBBB PPPPPPBBBBBBB
  3604. ;;
  3605. ;; Indentation needs to be taken from the line with the ``::`` and not from
  3606. ;; the first content line.
  3607. ;; `Indented Literal Blocks`_
  3608. ;; This is multiline.
  3609. (,(rst-re 'lin-beg 'lit-sta-2)
  3610. (2 rst-block-face)
  3611. (rst-font-lock-find-unindented-line-match
  3612. (rst-font-lock-find-unindented-line-limit t)
  3613. nil
  3614. (0 rst-literal-face append)))
  3615. ;; FIXME: `Quoted Literal Blocks`_ missing.
  3616. ;; This is multiline.
  3617. ;; `Doctest Blocks`_
  3618. ;; FIXME: This is wrong according to the specification:
  3619. ;;
  3620. ;; Doctest blocks are text blocks which begin with ">>> ", the Python
  3621. ;; interactive interpreter main prompt, and end with a blank line.
  3622. ;; Doctest blocks are treated as a special case of literal blocks,
  3623. ;; without requiring the literal block syntax. If both are present, the
  3624. ;; literal block syntax takes priority over Doctest block syntax:
  3625. ;;
  3626. ;; This is an ordinary paragraph.
  3627. ;;
  3628. ;; >>> print 'this is a Doctest block'
  3629. ;; this is a Doctest block
  3630. ;;
  3631. ;; The following is a literal block::
  3632. ;;
  3633. ;; >>> This is not recognized as a doctest block by
  3634. ;; reStructuredText. It *will* be recognized by the doctest
  3635. ;; module, though!
  3636. ;;
  3637. ;; Indentation is not required for doctest blocks.
  3638. (,(rst-re 'lin-beg '(:grp (:alt ">>>" ell-tag)) '(:grp ".+"))
  3639. (1 rst-block-face)
  3640. (2 rst-literal-face)))
  3641. "Keywords to highlight in rst mode.")
  3642. (defvar font-lock-beg)
  3643. (defvar font-lock-end)
  3644. (defun rst-font-lock-extend-region ()
  3645. "Extend the font-lock region if it might be in a multi-line construct.
  3646. Return non-nil if so. Font-lock region is from `font-lock-beg'
  3647. to `font-lock-end'."
  3648. (let ((r (rst-font-lock-extend-region-internal font-lock-beg font-lock-end)))
  3649. (when r
  3650. (setq font-lock-beg (car r))
  3651. (setq font-lock-end (cdr r))
  3652. t)))
  3653. (defun rst-font-lock-extend-region-internal (beg end)
  3654. "Check the region BEG / END for being in the middle of a multi-line construct.
  3655. Return nil if not or a cons with new values for BEG / END"
  3656. (let ((nbeg (rst-font-lock-extend-region-extend beg -1))
  3657. (nend (rst-font-lock-extend-region-extend end 1)))
  3658. (if (or nbeg nend)
  3659. (cons (or nbeg beg) (or nend end)))))
  3660. ;; FIXME refactoring: Use `rst-forward-line-strict' instead.
  3661. (defun rst-forward-line (&optional n)
  3662. "Like `forward-line' but always end up in column 0 and return accordingly.
  3663. Move N lines forward just as `forward-line'."
  3664. (let ((left (forward-line n)))
  3665. (if (bolp)
  3666. left
  3667. ;; FIXME: This may move back for positive n - is this desired?
  3668. (forward-line 0)
  3669. (- left (cl-signum n)))))
  3670. ;; FIXME: If a single line is made a section header by `rst-adjust' the header
  3671. ;; is not always fontified immediately.
  3672. (defun rst-font-lock-extend-region-extend (pt dir)
  3673. "Extend the region starting at point PT and extending in direction DIR.
  3674. Return extended point or nil if not moved."
  3675. ;; There are many potential multiline constructs but there are two groups
  3676. ;; which are really relevant. The first group consists of
  3677. ;;
  3678. ;; * comment lines without leading explicit markup tag and
  3679. ;;
  3680. ;; * literal blocks following "::"
  3681. ;;
  3682. ;; which are both indented. Thus indentation is the first thing recognized
  3683. ;; here. The second criteria is an explicit markup tag which may be a comment
  3684. ;; or a double colon at the end of a line.
  3685. ;;
  3686. ;; The second group consists of the adornment cases.
  3687. (if (not (get-text-property pt 'font-lock-multiline))
  3688. ;; Move only if we don't start inside a multiline construct already.
  3689. (save-match-data
  3690. (save-excursion
  3691. (let ( ; Non-empty non-indented line, explicit markup tag or literal
  3692. ; block tag.
  3693. (stop-re (rst-re '(:alt "[^ \t\n]"
  3694. (:seq hws-tag exm-tag)
  3695. (:seq ".*" dcl-tag lin-end)))))
  3696. ;; The comments below are for dir == -1 / dir == 1.
  3697. (goto-char pt)
  3698. (rst-forward-line-strict 0)
  3699. (setq pt (point))
  3700. (while (and (not (looking-at stop-re))
  3701. (zerop (rst-forward-line dir)))) ; try previous / next
  3702. ; line if it exists.
  3703. (if (looking-at (rst-re 'ado-beg-2-1)) ; may be an underline /
  3704. ; overline.
  3705. (if (zerop (rst-forward-line dir))
  3706. (if (looking-at (rst-re 'ttl-beg-1)) ; title found, i.e.
  3707. ; underline / overline
  3708. ; found.
  3709. (if (zerop (rst-forward-line dir))
  3710. (if (not
  3711. (looking-at (rst-re 'ado-beg-2-1))) ; no
  3712. ; overline
  3713. ; /
  3714. ; underline.
  3715. (rst-forward-line (- dir)))) ; step back to
  3716. ; title /
  3717. ; adornment.
  3718. (if (< dir 0) ; keep downward adornment.
  3719. (rst-forward-line (- dir))))) ; step back to adornment.
  3720. (if (looking-at (rst-re 'ttl-beg-1)) ; may be a title.
  3721. (if (zerop (rst-forward-line dir))
  3722. (if (not
  3723. (looking-at (rst-re 'ado-beg-2-1))) ; no overline /
  3724. ; underline.
  3725. (rst-forward-line (- dir)))))) ; step back to line.
  3726. (if (not (= (point) pt))
  3727. (point)))))))
  3728. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3729. ;; Indented blocks
  3730. (defun rst-forward-indented-block (&optional column limit)
  3731. ;; testcover: ok.
  3732. "Move forward across one indented block.
  3733. Find the next (i.e. excluding the current line) non-empty line
  3734. which is not indented at least to COLUMN (defaults to the column
  3735. of the point). Move point to first character of this line or the
  3736. first of the empty lines immediately before it and return that
  3737. position. If there is no such line before LIMIT (defaults to the
  3738. end of the buffer) return nil and do not move point."
  3739. (let (fnd candidate)
  3740. (setq fnd (rst-apply-indented-blocks
  3741. (line-beginning-position 2) ; Skip the current line
  3742. (or limit (point-max)) (or column (current-column))
  3743. #'(lambda (_count _in-first _in-sub in-super in-empty _relind)
  3744. (cond
  3745. (in-empty
  3746. (setq candidate (or candidate (line-beginning-position)))
  3747. nil)
  3748. (in-super
  3749. (or candidate (line-beginning-position)))
  3750. (t ; Non-empty, same or more indented line.
  3751. (setq candidate nil)
  3752. nil)))))
  3753. (when fnd
  3754. (goto-char fnd))))
  3755. (defvar rst-font-lock-find-unindented-line-begin nil
  3756. "Beginning of the match if `rst-font-lock-find-unindented-line-end'.")
  3757. (defvar rst-font-lock-find-unindented-line-end nil
  3758. "End of the match as determined by `rst-font-lock-find-unindented-line-limit'.
  3759. Also used as a trigger for `rst-font-lock-find-unindented-line-match'.")
  3760. (defun rst-font-lock-find-unindented-line-limit (ind-pnt)
  3761. "Find the next unindented line relative to indentation at IND-PNT.
  3762. Return this point, the end of the buffer or nil if nothing found.
  3763. If IND-PNT is `next' take the indentation from the next line if
  3764. this is not empty and indented more than the current one. If
  3765. IND-PNT is non-nil but not a number take the indentation from the
  3766. next non-empty line if this is indented more than the current one."
  3767. (setq rst-font-lock-find-unindented-line-begin ind-pnt)
  3768. (setq rst-font-lock-find-unindented-line-end
  3769. (save-match-data
  3770. (save-excursion
  3771. (when (not (numberp ind-pnt))
  3772. ;; Find indentation point in next line if any.
  3773. (setq ind-pnt
  3774. ;; FIXME: Should be refactored to two different functions
  3775. ;; giving their result to this function, may be
  3776. ;; integrated in caller.
  3777. (save-match-data
  3778. (let ((cur-ind (current-indentation)))
  3779. (if (eq ind-pnt 'next)
  3780. (when (and (rst-forward-line-strict 1 (point-max))
  3781. (< (point) (point-max)))
  3782. ;; Not at EOF.
  3783. (setq rst-font-lock-find-unindented-line-begin
  3784. (point))
  3785. (when (and (not (looking-at (rst-re 'lin-end)))
  3786. (> (current-indentation) cur-ind))
  3787. ;; Use end of indentation if non-empty line.
  3788. (looking-at (rst-re 'hws-tag))
  3789. (match-end 0)))
  3790. ;; Skip until non-empty line or EOF.
  3791. (while (and (rst-forward-line-strict 1 (point-max))
  3792. (< (point) (point-max))
  3793. (looking-at (rst-re 'lin-end))))
  3794. (when (< (point) (point-max))
  3795. ;; Not at EOF.
  3796. (setq rst-font-lock-find-unindented-line-begin
  3797. (point))
  3798. (when (> (current-indentation) cur-ind)
  3799. ;; Indentation bigger than line of departure.
  3800. (looking-at (rst-re 'hws-tag))
  3801. (match-end 0))))))))
  3802. (when ind-pnt
  3803. (goto-char ind-pnt)
  3804. (or (rst-forward-indented-block nil (point-max))
  3805. (point-max)))))))
  3806. (defun rst-font-lock-find-unindented-line-match (_limit)
  3807. "Set the match found earlier if match were found.
  3808. Match has been found by `rst-font-lock-find-unindented-line-limit'
  3809. the first time called or no match is found. Return non-nil if
  3810. match was found. _LIMIT is not used but mandated by the caller."
  3811. (when rst-font-lock-find-unindented-line-end
  3812. (set-match-data
  3813. (list rst-font-lock-find-unindented-line-begin
  3814. rst-font-lock-find-unindented-line-end))
  3815. (put-text-property rst-font-lock-find-unindented-line-begin
  3816. rst-font-lock-find-unindented-line-end
  3817. 'font-lock-multiline t)
  3818. ;; Make sure this is called only once.
  3819. (setq rst-font-lock-find-unindented-line-end nil)
  3820. t))
  3821. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3822. ;; Adornments
  3823. (defvar rst-font-lock-adornment-level nil
  3824. "Storage for `rst-font-lock-handle-adornment-matcher'.
  3825. Either section level of the current adornment or t for a transition.")
  3826. (defun rst-adornment-level (ado)
  3827. "Return section level for ADO or t for a transition.
  3828. If ADO is found in the hierarchy return its level. Otherwise
  3829. return a level one beyond the existing hierarchy."
  3830. (if (rst-Ado-is-transition ado)
  3831. t
  3832. (let ((hier (rst-Hdr-ado-map (rst-hdr-hierarchy))))
  3833. (1+ (or (rst-Ado-position ado hier)
  3834. (length hier))))))
  3835. (defvar rst-font-lock-adornment-match nil
  3836. "Storage for match for current adornment.
  3837. Set by `rst-font-lock-handle-adornment-pre-match-form'. Also used
  3838. as a trigger for `rst-font-lock-handle-adornment-matcher'.")
  3839. (defun rst-font-lock-handle-adornment-pre-match-form (ado ado-end)
  3840. "Determine limit for adornments.
  3841. Determine all things necessary for font-locking section titles
  3842. and transitions and put the result to `rst-font-lock-adornment-match'
  3843. and `rst-font-lock-adornment-level'. ADO is the complete adornment
  3844. matched. ADO-END is the point where ADO ends. Return the point
  3845. where the whole adorned construct ends.
  3846. Called as a PRE-MATCH-FORM in the sense of `font-lock-keywords'."
  3847. (let ((ttl (rst-classify-adornment ado ado-end)))
  3848. (if (not ttl)
  3849. (setq rst-font-lock-adornment-level nil
  3850. rst-font-lock-adornment-match nil)
  3851. (setq rst-font-lock-adornment-level
  3852. (rst-adornment-level (rst-Ttl-ado ttl)))
  3853. (setq rst-font-lock-adornment-match (rst-Ttl-match ttl))
  3854. (goto-char (rst-Ttl-get-beginning ttl))
  3855. (rst-Ttl-get-end ttl))))
  3856. (defun rst-font-lock-handle-adornment-matcher (_limit)
  3857. "Set the match found earlier if match were found.
  3858. Match has been found by
  3859. `rst-font-lock-handle-adornment-pre-match-form' the first time
  3860. called or no match is found. Return non-nil if match was found.
  3861. Called as a MATCHER in the sense of `font-lock-keywords'.
  3862. _LIMIT is not used but mandated by the caller."
  3863. (let ((match rst-font-lock-adornment-match))
  3864. ;; May run only once - enforce this.
  3865. (setq rst-font-lock-adornment-match nil)
  3866. (when match
  3867. (set-match-data match)
  3868. (goto-char (match-end 0))
  3869. (put-text-property (match-beginning 0) (match-end 0)
  3870. 'font-lock-multiline t)
  3871. t)))
  3872. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3873. ;; Compilation
  3874. (defgroup rst-compile nil
  3875. "Settings for support of conversion of reStructuredText
  3876. document with \\[rst-compile]."
  3877. :group 'rst
  3878. :version "21.1")
  3879. (defcustom rst-compile-toolsets
  3880. `((html ,(if (executable-find "rst2html.py") "rst2html.py" "rst2html")
  3881. ".html" nil)
  3882. (latex ,(if (executable-find "rst2latex.py") "rst2latex.py" "rst2latex")
  3883. ".tex" nil)
  3884. (newlatex ,(if (executable-find "rst2newlatex.py") "rst2newlatex.py"
  3885. "rst2newlatex")
  3886. ".tex" nil)
  3887. (pseudoxml ,(if (executable-find "rst2pseudoxml.py") "rst2pseudoxml.py"
  3888. "rst2pseudoxml")
  3889. ".xml" nil)
  3890. (xml ,(if (executable-find "rst2xml.py") "rst2xml.py" "rst2xml")
  3891. ".xml" nil)
  3892. (pdf ,(if (executable-find "rst2pdf.py") "rst2pdf.py" "rst2pdf")
  3893. ".pdf" nil)
  3894. (s5 ,(if (executable-find "rst2s5.py") "rst2s5.py" "rst2s5")
  3895. ".html" nil))
  3896. ;; FIXME: Add at least those converters officially supported like `rst2odt'
  3897. ;; and `rst2man'.
  3898. ;; FIXME: To make this really useful there should be a generic command the
  3899. ;; user gives one of the symbols and this way select the conversion to
  3900. ;; run. This should replace the toolset stuff somehow.
  3901. ;; FIXME: Allow a template for the conversion command so `rst2pdf ... -o ...'
  3902. ;; can be supported.
  3903. "Table describing the command to use for each tool-set.
  3904. An association list of the tool-set to a list of the (command to use,
  3905. extension of produced filename, options to the tool (nil or a
  3906. string)) to be used for converting the document."
  3907. ;; FIXME: These are not options but symbols which may be referenced by
  3908. ;; `rst-compile-*-toolset` below. The `:validate' keyword of
  3909. ;; `defcustom' may help to define this properly in newer Emacs
  3910. ;; versions (> 23.1).
  3911. :type '(alist :options (html latex newlatex pseudoxml xml pdf s5)
  3912. :key-type symbol
  3913. :value-type (list :tag "Specification"
  3914. (file :tag "Command")
  3915. (string :tag "File extension")
  3916. (choice :tag "Command options"
  3917. (const :tag "No options" nil)
  3918. (string :tag "Options"))))
  3919. :group 'rst-compile
  3920. :package-version "1.2.0")
  3921. (rst-testcover-defcustom)
  3922. ;; FIXME: Must be defcustom.
  3923. (defvar rst-compile-primary-toolset 'html
  3924. "The default tool-set for `rst-compile'.")
  3925. ;; FIXME: Must be defcustom.
  3926. (defvar rst-compile-secondary-toolset 'latex
  3927. "The default tool-set for `rst-compile' with a prefix argument.")
  3928. (defun rst-compile-find-conf ()
  3929. "Look for the configuration file in the parents of the current path."
  3930. (interactive)
  3931. (let ((file-name "docutils.conf")
  3932. (buffer-file (buffer-file-name)))
  3933. ;; Move up in the dir hierarchy till we find a change log file.
  3934. (let* ((dir (file-name-directory buffer-file))
  3935. (prevdir nil))
  3936. (while (and (or (not (string= dir prevdir))
  3937. (setq dir nil)
  3938. nil)
  3939. (not (file-exists-p (concat dir file-name))))
  3940. ;; Move up to the parent dir and try again.
  3941. (setq prevdir dir)
  3942. (setq dir (expand-file-name (file-name-directory
  3943. (directory-file-name
  3944. (file-name-directory dir))))))
  3945. (or (and dir (concat dir file-name)) nil))))
  3946. (require 'compile)
  3947. (defun rst-compile (&optional use-alt)
  3948. "Compile command to convert reST document into some output file.
  3949. Attempts to find configuration file, if it can, overrides the
  3950. options. There are two commands to choose from; with USE-ALT,
  3951. select the alternative tool-set."
  3952. (interactive "P")
  3953. ;; Note: maybe we want to check if there is a Makefile too and not do anything
  3954. ;; if that is the case. I dunno.
  3955. (cl-destructuring-bind
  3956. (command extension options
  3957. &aux (conffile (rst-compile-find-conf))
  3958. (bufname (file-name-nondirectory buffer-file-name)))
  3959. (cdr (assq (if use-alt
  3960. rst-compile-secondary-toolset
  3961. rst-compile-primary-toolset)
  3962. rst-compile-toolsets))
  3963. ;; Set compile-command before invocation of compile.
  3964. (setq-local
  3965. compile-command
  3966. (mapconcat
  3967. #'identity
  3968. (list command
  3969. (or options "")
  3970. (if conffile
  3971. (concat "--config=" (shell-quote-argument conffile))
  3972. "")
  3973. (shell-quote-argument bufname)
  3974. (shell-quote-argument (concat (file-name-sans-extension bufname)
  3975. extension)))
  3976. " "))
  3977. ;; Invoke the compile command.
  3978. (if (or compilation-read-command use-alt)
  3979. (call-interactively #'compile)
  3980. (compile compile-command))))
  3981. (defun rst-compile-alt-toolset ()
  3982. "Compile command with the alternative tool-set."
  3983. (interactive)
  3984. (rst-compile t))
  3985. (defun rst-compile-pseudo-region ()
  3986. "Show pseudo-XML rendering.
  3987. Rendering is done of the current active region, or of the entire
  3988. buffer, if the region is not selected."
  3989. ;; FIXME: The region should be given interactively.
  3990. (interactive)
  3991. (with-output-to-temp-buffer "*pseudoxml*"
  3992. (shell-command-on-region
  3993. (if mark-active (region-beginning) (point-min))
  3994. (if mark-active (region-end) (point-max))
  3995. (cadr (assq 'pseudoxml rst-compile-toolsets))
  3996. standard-output)))
  3997. ;; FIXME: Should be integrated in `rst-compile-toolsets'.
  3998. (defvar rst-pdf-program "xpdf"
  3999. "Program used to preview PDF files.")
  4000. (defun rst-compile-pdf-preview ()
  4001. "Convert the document to a PDF file and launch a preview program."
  4002. (interactive)
  4003. (let* ((tmp-filename (make-temp-file "rst_el" nil ".pdf"))
  4004. (command (format "%s %s %s && %s %s ; rm %s"
  4005. (cadr (assq 'pdf rst-compile-toolsets))
  4006. buffer-file-name tmp-filename
  4007. rst-pdf-program tmp-filename tmp-filename)))
  4008. (start-process-shell-command "rst-pdf-preview" nil command)
  4009. ;; Note: you could also use (compile command) to view the compilation
  4010. ;; output.
  4011. ))
  4012. ;; FIXME: Should be integrated in `rst-compile-toolsets' defaulting to
  4013. ;; something like `browse-url'.
  4014. (defvar rst-slides-program "firefox"
  4015. "Program used to preview S5 slides.")
  4016. (defun rst-compile-slides-preview ()
  4017. "Convert the document to an S5 slide presentation and launch a preview program."
  4018. (interactive)
  4019. (let* ((tmp-filename (make-temp-file "rst_el" nil ".html"))
  4020. (command (format "%s %s %s && %s %s ; rm %s"
  4021. (cadr (assq 's5 rst-compile-toolsets))
  4022. buffer-file-name tmp-filename
  4023. rst-slides-program tmp-filename tmp-filename)))
  4024. (start-process-shell-command "rst-slides-preview" nil command)
  4025. ;; Note: you could also use (compile command) to view the compilation
  4026. ;; output.
  4027. ))
  4028. ;; FIXME: Add `rst-compile-html-preview'.
  4029. ;; FIXME: Add support for `restview` (http://mg.pov.lt/restview/). May be a
  4030. ;; more general facility for calling commands on a reST file would make
  4031. ;; sense.
  4032. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4033. ;; Imenu support
  4034. ;; FIXME: Consider a key binding. A key binding needs to definitely switch on
  4035. ;; `which-func-mode' - i.e. `which-func-modes' must be set properly.
  4036. ;; Based on ideas from Masatake YAMATO <yamato@redhat.com>.
  4037. (defun rst-imenu-convert-cell (stn)
  4038. "Convert a STN to an Imenu index node and return it."
  4039. (let ((ttl (rst-Stn-ttl stn))
  4040. (children (rst-Stn-children stn))
  4041. (pos (rst-Stn-get-title-beginning stn))
  4042. (txt (rst-Stn-get-text stn ""))
  4043. (pfx " ")
  4044. (sfx "")
  4045. name)
  4046. (when ttl
  4047. (let ((hdr (rst-Ttl-hdr ttl)))
  4048. (setq pfx (char-to-string (rst-Hdr-get-char hdr)))
  4049. (when (rst-Hdr-is-over-and-under hdr)
  4050. (setq sfx pfx))))
  4051. ;; FIXME: Overline adornment characters need to be in front so they
  4052. ;; become visible even for long title lines. May be an additional
  4053. ;; level number is also useful.
  4054. (setq name (format "%s%s%s" pfx txt sfx))
  4055. (cons name ; The name of the entry.
  4056. (if children
  4057. (cons ; The entry has a submenu.
  4058. (cons name pos) ; The entry itself.
  4059. (mapcar #'rst-imenu-convert-cell children)) ; The children.
  4060. pos)))) ; The position of a plain entry.
  4061. ;; FIXME: Document title and subtitle need to be handled properly. They should
  4062. ;; get an own "Document" top level entry.
  4063. (defun rst-imenu-create-index ()
  4064. "Create index for Imenu.
  4065. Return as described for `imenu--index-alist'."
  4066. (rst-reset-section-caches)
  4067. (let ((root (rst-all-stn)))
  4068. (when root
  4069. (mapcar #'rst-imenu-convert-cell (rst-Stn-children root)))))
  4070. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4071. ;; Convenience functions
  4072. ;; FIXME: Unbound command - should be bound or removed.
  4073. (defun rst-replace-lines (fromchar tochar)
  4074. "Replace flush-left lines of FROMCHAR with equal-length lines of TOCHAR."
  4075. (interactive "\
  4076. cSearch for flush-left lines of char:
  4077. cand replace with char: ")
  4078. (save-excursion
  4079. (let ((searchre (rst-re "^" fromchar "+\\( *\\)$"))
  4080. (found 0))
  4081. (while (search-forward-regexp searchre nil t)
  4082. (setq found (1+ found))
  4083. (goto-char (match-beginning 1))
  4084. (let ((width (current-column)))
  4085. (rst-delete-entire-line 0)
  4086. (insert-char tochar width)))
  4087. (message "%d lines replaced." found))))
  4088. ;; FIXME: Unbound command - should be bound or removed.
  4089. (defun rst-join-paragraph ()
  4090. "Join lines in current paragraph into one line, removing end-of-lines."
  4091. (interactive)
  4092. (let ((fill-column 65000)) ; Some big number.
  4093. (call-interactively #'fill-paragraph)))
  4094. ;; FIXME: Unbound command - should be bound or removed.
  4095. (defun rst-force-fill-paragraph ()
  4096. "Fill paragraph at point, first joining the paragraph's lines into one.
  4097. This is useful for filling list item paragraphs."
  4098. (interactive)
  4099. (rst-join-paragraph)
  4100. (fill-paragraph nil))
  4101. ;; FIXME: Unbound command - should be bound or removed.
  4102. ;; Generic character repeater function.
  4103. ;; For sections, better to use the specialized function above, but this can
  4104. ;; be useful for creating separators.
  4105. (defun rst-repeat-last-character (use-next)
  4106. "Fill the current line using the last character on the current line.
  4107. Fill up to the length of the preceding line or up to `fill-column' if preceding
  4108. line is empty.
  4109. If USE-NEXT, use the next line rather than the preceding line.
  4110. If the current line is longer than the desired length, shave the characters off
  4111. the current line to fit the desired length.
  4112. As an added convenience, if the command is repeated immediately, the alternative
  4113. column is used (fill-column vs. end of previous/next line)."
  4114. (interactive "P")
  4115. (let* ((curcol (current-column))
  4116. (curline (+ (count-lines (point-min) (point))
  4117. (if (zerop curcol) 1 0)))
  4118. (lbp (line-beginning-position 0))
  4119. (prevcol (if (and (= curline 1) (not use-next))
  4120. fill-column
  4121. (save-excursion
  4122. (forward-line (if use-next 1 -1))
  4123. (end-of-line)
  4124. (skip-chars-backward " \t" lbp)
  4125. (let ((cc (current-column)))
  4126. (if (zerop cc) fill-column cc)))))
  4127. (rightmost-column
  4128. (cond ((equal last-command 'rst-repeat-last-character)
  4129. (if (= curcol fill-column) prevcol fill-column))
  4130. (t (save-excursion
  4131. (if (zerop prevcol) fill-column prevcol))))))
  4132. (end-of-line)
  4133. (if (> (current-column) rightmost-column)
  4134. ;; Shave characters off the end.
  4135. (delete-region (- (point)
  4136. (- (current-column) rightmost-column))
  4137. (point))
  4138. ;; Fill with last characters.
  4139. (insert-char (preceding-char)
  4140. (- rightmost-column (current-column))))))
  4141. ;; LocalWords: docutils http sourceforge rst html wp svn svnroot txt reST regex
  4142. ;; LocalWords: regexes alist seq alt grp keymap abbrev overline overlines toc
  4143. ;; LocalWords: XML PNT propertized init referenceable
  4144. (provide 'rst)
  4145. ;; Local Variables:
  4146. ;; sentence-end-double-space: t
  4147. ;; End:
  4148. ;;; rst.el ends here