cus-edit.el 167 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860
  1. ;;; cus-edit.el --- tools for customizing Emacs and Lisp packages -*- lexical-binding:t -*-
  2. ;;
  3. ;; Copyright (C) 1996-1997, 1999-2017 Free Software Foundation, Inc.
  4. ;;
  5. ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
  6. ;; Maintainer: emacs-devel@gnu.org
  7. ;; Keywords: help, faces
  8. ;; Package: emacs
  9. ;; This file is part of GNU Emacs.
  10. ;; GNU Emacs is free software: you can redistribute it and/or modify
  11. ;; it under the terms of the GNU General Public License as published by
  12. ;; the Free Software Foundation, either version 3 of the License, or
  13. ;; (at your option) any later version.
  14. ;; GNU Emacs is distributed in the hope that it will be useful,
  15. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;; GNU General Public License for more details.
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  20. ;;; Commentary:
  21. ;;
  22. ;; This file implements the code to create and edit customize buffers.
  23. ;;
  24. ;; See `custom.el'.
  25. ;; No commands should have names starting with `custom-' because
  26. ;; that interferes with completion. Use `customize-' for commands
  27. ;; that the user will run with M-x, and `Custom-' for interactive commands.
  28. ;; The identity of a customize option is represented by a Lisp symbol.
  29. ;; The following values are associated with an option.
  30. ;; 0. The current value.
  31. ;; This is the value of the option as seen by "the rest of Emacs".
  32. ;; Usually extracted by 'default-value', but can be extracted with
  33. ;; different means if the option symbol has the 'custom-get'
  34. ;; property. Similarly, set-default (or the 'custom-set' property)
  35. ;; can set it.
  36. ;; 1. The widget value.
  37. ;; This is the value shown in the widget in a customize buffer.
  38. ;; 2. The customized value.
  39. ;; This is the last value given to the option through customize.
  40. ;; It is stored in the 'customized-value' property of the option, in a
  41. ;; cons-cell whose car evaluates to the customized value.
  42. ;; 3. The saved value.
  43. ;; This is last value saved from customize.
  44. ;; It is stored in the 'saved-value' property of the option, in a
  45. ;; cons-cell whose car evaluates to the saved value.
  46. ;; 4. The standard value.
  47. ;; This is the value given in the 'defcustom' declaration.
  48. ;; It is stored in the 'standard-value' property of the option, in a
  49. ;; cons-cell whose car evaluates to the standard value.
  50. ;; 5. The "think" value.
  51. ;; This is what customize thinks the current value should be.
  52. ;; This is the customized value, if any such value exists, otherwise
  53. ;; the saved value, if that exists, and as a last resort the standard
  54. ;; value.
  55. ;; The reason for storing values unevaluated: This is so you can have
  56. ;; values that depend on the environment. For example, you can have a
  57. ;; variable that has one value when Emacs is running under a window
  58. ;; system, and another value on a tty. Since the evaluation is only done
  59. ;; when the variable is first initialized, this is only relevant for the
  60. ;; saved (and standard) values, but affect others values for
  61. ;; compatibility.
  62. ;; You can see (and modify and save) this unevaluated value by selecting
  63. ;; "Show Saved Lisp Expression" from the Lisp interface. This will
  64. ;; give you the unevaluated saved value, if any, otherwise the
  65. ;; unevaluated standard value.
  66. ;; The possible states for a customize widget are:
  67. ;; 0. unknown
  68. ;; The state has not been determined yet.
  69. ;; 1. modified
  70. ;; The widget value is different from the current value.
  71. ;; 2. changed
  72. ;; The current value is different from the "think" value.
  73. ;; 3. set
  74. ;; The "think" value is the customized value.
  75. ;; 4. saved
  76. ;; The "think" value is the saved value.
  77. ;; 5. standard
  78. ;; The "think" value is the standard value.
  79. ;; 6. rogue
  80. ;; There is no standard value. This means that the variable was
  81. ;; not defined with defcustom, nor handled in cus-start.el. Most
  82. ;; standard interactive Custom commands do not let you create a
  83. ;; Custom buffer containing such variables. However, such Custom
  84. ;; buffers can be created, for instance, by calling
  85. ;; `customize-apropos' with a prefix arg or by calling
  86. ;; `customize-option' non-interactively.
  87. ;; 7. hidden
  88. ;; There is no widget value.
  89. ;; 8. mismatch
  90. ;; The widget value is not valid member of the :type specified for the
  91. ;; option.
  92. ;;; Code:
  93. (require 'cus-face)
  94. (require 'wid-edit)
  95. (defvar custom-versions-load-alist) ; from cus-load
  96. (defvar recentf-exclude) ; from recentf.el
  97. (condition-case nil
  98. (require 'cus-load)
  99. (error nil))
  100. (condition-case nil
  101. (require 'cus-start)
  102. (error nil))
  103. (put 'custom-define-hook 'custom-type 'hook)
  104. (put 'custom-define-hook 'standard-value '(nil))
  105. (custom-add-to-group 'customize 'custom-define-hook 'custom-variable)
  106. ;;; Customization Groups.
  107. (defgroup emacs nil
  108. "Customization of the One True Editor."
  109. :link '(custom-manual "(emacs)Top"))
  110. ;; Most of these groups are stolen from `finder.el',
  111. (defgroup editing nil
  112. "Basic text editing facilities."
  113. :group 'emacs)
  114. (defgroup convenience nil
  115. "Convenience features for faster editing."
  116. :group 'emacs)
  117. (defgroup files nil
  118. "Support for editing files."
  119. :group 'emacs)
  120. (defgroup wp nil
  121. "Support for editing text files.
  122. Use group `text' for this instead. This group is deprecated."
  123. :group 'emacs)
  124. (defgroup text nil
  125. "Support for editing text files."
  126. :group 'emacs
  127. ;; Inherit from deprecated `wp' for compatibility, for now.
  128. :group 'wp)
  129. (defgroup data nil
  130. "Support for editing binary data files."
  131. :group 'emacs)
  132. (defgroup abbrev nil
  133. "Abbreviation handling, typing shortcuts, macros."
  134. :tag "Abbreviations"
  135. :group 'convenience)
  136. (defgroup matching nil
  137. "Various sorts of searching and matching."
  138. :group 'editing)
  139. (defgroup emulations nil
  140. "Emulations of other editors."
  141. :link '(custom-manual "(emacs)Emulation")
  142. :group 'editing)
  143. (defgroup external nil
  144. "Interfacing to external utilities."
  145. :group 'emacs)
  146. (defgroup comm nil
  147. "Communications, networking, and remote access to files."
  148. :tag "Communication"
  149. :group 'emacs)
  150. (defgroup processes nil
  151. "Process, subshell, compilation, and job control support."
  152. :group 'external)
  153. (defgroup programming nil
  154. "Support for programming in other languages."
  155. :group 'emacs)
  156. (defgroup languages nil
  157. "Modes for editing programming languages."
  158. :group 'programming)
  159. (defgroup lisp nil
  160. "Lisp support, including Emacs Lisp."
  161. :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
  162. :group 'languages
  163. :group 'development)
  164. (defgroup c nil
  165. "Support for the C language and related languages."
  166. :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
  167. :link '(custom-manual "(ccmode)")
  168. :group 'languages)
  169. (defgroup tools nil
  170. "Programming tools."
  171. :group 'programming)
  172. (defgroup applications nil
  173. "Applications written in Emacs."
  174. :group 'emacs)
  175. (defgroup calendar nil
  176. "Calendar and time management support."
  177. :group 'applications)
  178. (defgroup mail nil
  179. "Modes for electronic-mail handling."
  180. :group 'applications)
  181. (defgroup news nil
  182. "Reading and posting to newsgroups."
  183. :link '(custom-manual "(gnus)")
  184. :group 'applications)
  185. (defgroup games nil
  186. "Games, jokes and amusements."
  187. :group 'applications)
  188. (defgroup development nil
  189. "Support for further development of Emacs."
  190. :group 'emacs)
  191. (defgroup docs nil
  192. "Support for Emacs documentation."
  193. :group 'development)
  194. (defgroup extensions nil
  195. "Emacs Lisp language extensions."
  196. :group 'development)
  197. (defgroup internal nil
  198. "Code for Emacs internals, build process, defaults."
  199. :group 'development)
  200. (defgroup maint nil
  201. "Maintenance aids for the Emacs development group."
  202. :tag "Maintenance"
  203. :group 'development)
  204. (defgroup environment nil
  205. "Fitting Emacs with its environment."
  206. :group 'emacs)
  207. (defgroup hardware nil
  208. "Support for interfacing with miscellaneous hardware."
  209. :group 'environment)
  210. (defgroup terminals nil
  211. "Support for terminal types."
  212. :group 'environment)
  213. (defgroup unix nil
  214. "Interfaces, assistants, and emulators for UNIX features."
  215. :group 'environment)
  216. (defgroup i18n nil
  217. "Internationalization and alternate character-set support."
  218. :link '(custom-manual "(emacs)International")
  219. :group 'environment
  220. :group 'editing)
  221. (defgroup x nil
  222. "The X Window system."
  223. :group 'environment)
  224. (defgroup frames nil
  225. "Support for Emacs frames and window systems."
  226. :group 'environment)
  227. (defgroup tex nil
  228. "Code related to the TeX formatter."
  229. :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
  230. :group 'text)
  231. (defgroup faces nil
  232. "Support for multiple fonts."
  233. :group 'emacs)
  234. (defgroup help nil
  235. "Support for Emacs help systems."
  236. :group 'emacs)
  237. (defgroup multimedia nil
  238. "Non-textual support, specifically images and sound."
  239. :group 'emacs)
  240. (defgroup local nil
  241. "Code local to your site."
  242. :group 'emacs)
  243. (defgroup customize '((widgets custom-group))
  244. "Customization of the Customization support."
  245. :prefix "custom-"
  246. :group 'help)
  247. (defgroup custom-faces nil
  248. "Faces used by customize."
  249. :group 'customize
  250. :group 'faces)
  251. (defgroup custom-browse nil
  252. "Control customize browser."
  253. :prefix "custom-"
  254. :group 'customize)
  255. (defgroup custom-buffer nil
  256. "Control customize buffers."
  257. :prefix "custom-"
  258. :group 'customize)
  259. (defgroup custom-menu nil
  260. "Control customize menus."
  261. :prefix "custom-"
  262. :group 'customize)
  263. (defgroup alloc nil
  264. "Storage allocation and gc for GNU Emacs Lisp interpreter."
  265. :tag "Storage Allocation"
  266. :group 'internal)
  267. (defgroup undo nil
  268. "Undoing changes in buffers."
  269. :link '(custom-manual "(emacs)Undo")
  270. :group 'editing)
  271. (defgroup mode-line nil
  272. "Contents of the mode line."
  273. :group 'environment)
  274. (defgroup editing-basics nil
  275. "Most basic editing facilities."
  276. :group 'editing)
  277. (defgroup display nil
  278. "How characters are displayed in buffers."
  279. :group 'environment)
  280. (defgroup execute nil
  281. "Executing external commands."
  282. :group 'processes)
  283. (defgroup installation nil
  284. "The Emacs installation."
  285. :group 'environment)
  286. (defgroup dired nil
  287. "Directory editing."
  288. :group 'environment)
  289. (defgroup limits nil
  290. "Internal Emacs limits."
  291. :group 'internal)
  292. (defgroup debug nil
  293. "Debugging Emacs itself."
  294. :group 'development)
  295. (defgroup keyboard nil
  296. "Input from the keyboard."
  297. :group 'environment)
  298. (defgroup menu nil
  299. "Input from the menus."
  300. :group 'environment)
  301. (defgroup dnd nil
  302. "Handling data from drag and drop."
  303. :group 'environment)
  304. (defgroup auto-save nil
  305. "Preventing accidental loss of data."
  306. :group 'files)
  307. (defgroup processes-basics nil
  308. "Basic stuff dealing with processes."
  309. :group 'processes)
  310. (defgroup mule nil
  311. "MULE Emacs internationalization."
  312. :group 'i18n)
  313. (defgroup windows nil
  314. "Windows within a frame."
  315. :link '(custom-manual "(emacs)Windows")
  316. :group 'environment)
  317. ;;; Custom mode keymaps
  318. (defvar custom-mode-map
  319. (let ((map (make-keymap)))
  320. (set-keymap-parent map widget-keymap)
  321. (define-key map [remap self-insert-command] 'Custom-no-edit)
  322. (define-key map "\^m" 'Custom-newline)
  323. (define-key map " " 'scroll-up-command)
  324. (define-key map [?\S-\ ] 'scroll-down-command)
  325. (define-key map "\177" 'scroll-down-command)
  326. (define-key map "\C-c\C-c" 'Custom-set)
  327. (define-key map "\C-x\C-s" 'Custom-save)
  328. (define-key map "q" 'Custom-buffer-done)
  329. (define-key map "u" 'Custom-goto-parent)
  330. (define-key map "n" 'widget-forward)
  331. (define-key map "p" 'widget-backward)
  332. map)
  333. "Keymap for `Custom-mode'.")
  334. (defvar custom-mode-link-map
  335. (let ((map (make-keymap)))
  336. (set-keymap-parent map custom-mode-map)
  337. (define-key map [down-mouse-2] nil)
  338. (define-key map [down-mouse-1] 'mouse-drag-region)
  339. (define-key map [mouse-2] 'widget-move-and-invoke)
  340. map)
  341. "Local keymap for links in `Custom-mode'.")
  342. (defvar custom-field-keymap
  343. (let ((map (copy-keymap widget-field-keymap)))
  344. (define-key map "\C-c\C-c" 'Custom-set)
  345. (define-key map "\C-x\C-s" 'Custom-save)
  346. map)
  347. "Keymap used inside editable fields in customization buffers.")
  348. (widget-put (get 'editable-field 'widget-type) :keymap custom-field-keymap)
  349. ;;; Utilities.
  350. (defun custom-split-regexp-maybe (regexp)
  351. "If REGEXP is a string, split it to a list at `\\|'.
  352. You can get the original back from the result with:
  353. (mapconcat \\='identity result \"\\|\")
  354. IF REGEXP is not a string, return it unchanged."
  355. (if (stringp regexp)
  356. (split-string regexp "\\\\|")
  357. regexp))
  358. (defun custom-variable-prompt ()
  359. "Prompt for a custom variable, defaulting to the variable at point.
  360. Return a list suitable for use in `interactive'."
  361. (let* ((v (variable-at-point))
  362. (default (and (symbolp v) (custom-variable-p v) (symbol-name v)))
  363. (enable-recursive-minibuffers t)
  364. val)
  365. (setq val (completing-read
  366. (if default (format "Customize variable (default %s): " default)
  367. "Customize variable: ")
  368. obarray 'custom-variable-p t nil nil default))
  369. (list (if (equal val "")
  370. (if (symbolp v) v nil)
  371. (intern val)))))
  372. (defun custom-menu-filter (menu widget)
  373. "Convert MENU to the form used by `widget-choose'.
  374. MENU should be in the same format as `custom-variable-menu'.
  375. WIDGET is the widget to apply the filter entries of MENU on."
  376. (let ((result nil)
  377. current name action filter)
  378. (while menu
  379. (setq current (car menu)
  380. name (nth 0 current)
  381. action (nth 1 current)
  382. filter (nth 2 current)
  383. menu (cdr menu))
  384. (if (or (null filter) (funcall filter widget))
  385. (push (cons name action) result)
  386. (push name result)))
  387. (nreverse result)))
  388. ;;; Unlispify.
  389. (defvar custom-prefix-list nil
  390. "List of prefixes that should be ignored by `custom-unlispify'.")
  391. (defcustom custom-unlispify-menu-entries t
  392. "Display menu entries as words instead of symbols if non-nil."
  393. :group 'custom-menu
  394. :type 'boolean)
  395. (defcustom custom-unlispify-remove-prefixes nil
  396. "Non-nil means remove group prefixes from option names in buffer.
  397. Discarding prefixes often leads to confusing names for options
  398. and faces in Customize buffers, so do not set this to a non-nil
  399. value unless you are sure you know what it does."
  400. :group 'custom-menu
  401. :group 'custom-buffer
  402. :type 'boolean)
  403. (defun custom-unlispify-menu-entry (symbol &optional no-suffix)
  404. "Convert SYMBOL into a menu entry."
  405. (cond ((not custom-unlispify-menu-entries)
  406. (symbol-name symbol))
  407. ((get symbol 'custom-tag)
  408. (if no-suffix
  409. (get symbol 'custom-tag)
  410. (concat (get symbol 'custom-tag) "...")))
  411. (t
  412. (with-current-buffer (get-buffer-create " *Custom-Work*")
  413. (erase-buffer)
  414. (princ symbol (current-buffer))
  415. (goto-char (point-min))
  416. (if custom-unlispify-remove-prefixes
  417. (let ((prefixes custom-prefix-list)
  418. prefix)
  419. (while prefixes
  420. (setq prefix (car prefixes))
  421. (if (search-forward prefix (+ (point) (length prefix)) t)
  422. (progn
  423. (setq prefixes nil)
  424. (delete-region (point-min) (point)))
  425. (setq prefixes (cdr prefixes))))))
  426. (subst-char-in-region (point-min) (point-max) ?- ?\s t)
  427. (capitalize-region (point-min) (point-max))
  428. (unless no-suffix
  429. (goto-char (point-max))
  430. (insert "..."))
  431. (buffer-string)))))
  432. (defcustom custom-unlispify-tag-names t
  433. "Display tag names as words instead of symbols if non-nil."
  434. :group 'custom-buffer
  435. :type 'boolean)
  436. (defun custom-unlispify-tag-name (symbol)
  437. "Convert SYMBOL into a menu entry."
  438. (let ((custom-unlispify-menu-entries custom-unlispify-tag-names))
  439. (custom-unlispify-menu-entry symbol t)))
  440. (defun custom-prefix-add (symbol prefixes)
  441. "Add SYMBOL to list of ignored PREFIXES."
  442. (cons (or (get symbol 'custom-prefix)
  443. (concat (symbol-name symbol) "-"))
  444. prefixes))
  445. ;;; Guess.
  446. (defcustom custom-guess-name-alist
  447. '(("-p\\'" boolean)
  448. ("-flag\\'" boolean)
  449. ("-hook\\'" hook)
  450. ("-face\\'" face)
  451. ("-file\\'" file)
  452. ("-function\\'" function)
  453. ("-functions\\'" (repeat function))
  454. ("-list\\'" (repeat sexp))
  455. ("-alist\\'" (alist :key-type sexp :value-type sexp)))
  456. "Alist of (MATCH TYPE).
  457. MATCH should be a regexp matching the name of a symbol, and TYPE should
  458. be a widget suitable for editing the value of that symbol. The TYPE
  459. of the first entry where MATCH matches the name of the symbol will be
  460. used.
  461. This is used for guessing the type of variables not declared with
  462. customize."
  463. :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type")))
  464. :group 'custom-buffer)
  465. (defcustom custom-guess-doc-alist
  466. '(("\\`\\*?Non-nil " boolean))
  467. "Alist of (MATCH TYPE).
  468. MATCH should be a regexp matching a documentation string, and TYPE
  469. should be a widget suitable for editing the value of a variable with
  470. that documentation string. The TYPE of the first entry where MATCH
  471. matches the name of the symbol will be used.
  472. This is used for guessing the type of variables not declared with
  473. customize."
  474. :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type")))
  475. :group 'custom-buffer)
  476. (defun custom-guess-type (symbol)
  477. "Guess a widget suitable for editing the value of SYMBOL.
  478. This is done by matching SYMBOL with `custom-guess-name-alist' and
  479. if that fails, the doc string with `custom-guess-doc-alist'."
  480. (let ((name (symbol-name symbol))
  481. (names custom-guess-name-alist)
  482. current found)
  483. (while names
  484. (setq current (car names)
  485. names (cdr names))
  486. (when (string-match-p (nth 0 current) name)
  487. (setq found (nth 1 current)
  488. names nil)))
  489. (unless found
  490. (let ((doc (documentation-property symbol 'variable-documentation t))
  491. (docs custom-guess-doc-alist))
  492. (when doc
  493. (while docs
  494. (setq current (car docs)
  495. docs (cdr docs))
  496. (when (string-match-p (nth 0 current) doc)
  497. (setq found (nth 1 current)
  498. docs nil))))))
  499. found))
  500. ;;; Sorting.
  501. ;;;###autoload
  502. (defcustom custom-browse-sort-alphabetically nil
  503. "If non-nil, sort customization group alphabetically in `custom-browse'."
  504. :type 'boolean
  505. :group 'custom-browse)
  506. (defcustom custom-browse-order-groups nil
  507. "If non-nil, order group members within each customization group.
  508. If `first', order groups before non-groups.
  509. If `last', order groups after non-groups."
  510. :type '(choice (const first)
  511. (const last)
  512. (const :tag "none" nil))
  513. :group 'custom-browse)
  514. (defcustom custom-browse-only-groups nil
  515. "If non-nil, show group members only within each customization group."
  516. :type 'boolean
  517. :group 'custom-browse)
  518. ;;;###autoload
  519. (defcustom custom-buffer-sort-alphabetically t
  520. "Whether to sort customization groups alphabetically in Custom buffer."
  521. :type 'boolean
  522. :group 'custom-buffer
  523. :version "24.1")
  524. (defcustom custom-buffer-order-groups 'last
  525. "If non-nil, order group members within each customization group.
  526. If `first', order groups before non-groups.
  527. If `last', order groups after non-groups."
  528. :type '(choice (const first)
  529. (const last)
  530. (const :tag "none" nil))
  531. :group 'custom-buffer)
  532. ;;;###autoload
  533. (defcustom custom-menu-sort-alphabetically nil
  534. "If non-nil, sort each customization group alphabetically in menus."
  535. :type 'boolean
  536. :group 'custom-menu)
  537. (defcustom custom-menu-order-groups 'first
  538. "If non-nil, order group members within each customization group.
  539. If `first', order groups before non-groups.
  540. If `last', order groups after non-groups."
  541. :type '(choice (const first)
  542. (const last)
  543. (const :tag "none" nil))
  544. :group 'custom-menu)
  545. (defun custom-sort-items (items sort-alphabetically order-groups)
  546. "Return a sorted copy of ITEMS.
  547. ITEMS should be a list of `custom-group' properties.
  548. If SORT-ALPHABETICALLY non-nil, sort alphabetically.
  549. If ORDER-GROUPS is `first' order groups before non-groups, if `last' order
  550. groups after non-groups, if nil do not order groups at all."
  551. (sort (copy-sequence items)
  552. (lambda (a b)
  553. (let ((typea (nth 1 a)) (typeb (nth 1 b))
  554. (namea (nth 0 a)) (nameb (nth 0 b)))
  555. (cond ((not order-groups)
  556. ;; Since we don't care about A and B order, maybe sort.
  557. (when sort-alphabetically
  558. (string-lessp namea nameb)))
  559. ((eq typea 'custom-group)
  560. ;; If B is also a group, maybe sort. Otherwise, order A and B.
  561. (if (eq typeb 'custom-group)
  562. (when sort-alphabetically
  563. (string-lessp namea nameb))
  564. (eq order-groups 'first)))
  565. ((eq typeb 'custom-group)
  566. ;; Since A cannot be a group, order A and B.
  567. (eq order-groups 'last))
  568. (sort-alphabetically
  569. ;; Since A and B cannot be groups, sort.
  570. (string-lessp namea nameb)))))))
  571. ;;; Custom Mode Commands.
  572. ;; This variable is used by `custom-tool-bar-map', or directly by
  573. ;; `custom-buffer-create-internal' if `custom-buffer-verbose-help' is non-nil.
  574. (defvar custom-commands
  575. '((" Apply " Custom-set t
  576. "Apply settings (for the current session only)."
  577. "index"
  578. "Apply")
  579. (" Apply and Save " Custom-save
  580. (or custom-file user-init-file)
  581. "Apply settings and save for future sessions."
  582. "save"
  583. "Save")
  584. (" Undo Edits " Custom-reset-current t
  585. "Restore customization buffer to reflect existing settings."
  586. "refresh"
  587. "Undo")
  588. (" Reset Customizations " Custom-reset-saved t
  589. "Undo any settings applied only for the current session."
  590. "undo"
  591. "Reset")
  592. (" Erase Customizations " Custom-reset-standard
  593. (or custom-file user-init-file)
  594. "Un-customize settings in this and future sessions."
  595. "delete"
  596. "Uncustomize")
  597. (" Help for Customize " Custom-help t
  598. "Get help for using Customize."
  599. "help"
  600. "Help")
  601. (" Exit " Custom-buffer-done t "Exit Customize." "exit" "Exit")))
  602. (defun Custom-help ()
  603. "Read the node on Easy Customization in the Emacs manual."
  604. (interactive)
  605. (info "(emacs)Easy Customization"))
  606. (defvar custom-reset-menu
  607. '(("Undo Edits in Customization Buffer" . Custom-reset-current)
  608. ("Revert This Session's Customizations" . Custom-reset-saved)
  609. ("Erase Customizations" . Custom-reset-standard))
  610. "Alist of actions for the `Reset' button.
  611. The key is a string containing the name of the action, the value is a
  612. Lisp function taking the widget as an element which will be called
  613. when the action is chosen.")
  614. (defvar custom-options nil
  615. "Customization widgets in the current buffer.")
  616. (defun custom-command-apply (fun query &optional strong-query)
  617. "Call function FUN on all widgets in `custom-options'.
  618. If there is more than one widget, ask user for confirmation using
  619. the query string QUERY, using `y-or-n-p' if STRONG-QUERY is nil,
  620. and `yes-or-no-p' otherwise. Return non-nil if the functionality
  621. has been executed, nil otherwise."
  622. (if (or (and (= 1 (length custom-options))
  623. (memq (widget-type (car custom-options))
  624. '(custom-variable custom-face)))
  625. (funcall (if strong-query 'yes-or-no-p 'y-or-n-p) query))
  626. (progn (mapc fun custom-options) t)
  627. (message "Aborted")
  628. nil))
  629. (defun Custom-set (&rest _ignore)
  630. "Set the current value of all edited settings in the buffer."
  631. (interactive)
  632. (custom-command-apply
  633. (lambda (child)
  634. (when (eq (widget-get child :custom-state) 'modified)
  635. (widget-apply child :custom-set)))
  636. "Set all values according to this buffer? "))
  637. (defun Custom-save (&rest _ignore)
  638. "Set all edited settings, then save all settings that have been set.
  639. If a setting was edited and set before, this saves it. If a
  640. setting was merely edited before, this sets it then saves it."
  641. (interactive)
  642. (when (custom-command-apply
  643. (lambda (child)
  644. (when (memq (widget-get child :custom-state)
  645. '(modified set changed rogue))
  646. (widget-apply child :custom-mark-to-save)))
  647. "Save all settings in this buffer? " t)
  648. ;; Save changes to buffer and redraw.
  649. (custom-save-all)
  650. (dolist (child custom-options)
  651. (widget-apply child :custom-state-set-and-redraw))))
  652. (defun custom-reset (_widget &optional event)
  653. "Select item from reset menu."
  654. (let* ((completion-ignore-case t)
  655. (answer (widget-choose "Reset settings"
  656. custom-reset-menu
  657. event)))
  658. (if answer
  659. (funcall answer))))
  660. (defun Custom-reset-current (&rest _ignore)
  661. "Reset all edited settings in the buffer to show their current values."
  662. (interactive)
  663. (custom-command-apply
  664. (lambda (widget)
  665. (if (memq (widget-get widget :custom-state) '(modified changed))
  666. (widget-apply widget :custom-reset-current)))
  667. "Reset all settings' buffer text to show current values? "))
  668. (defun Custom-reset-saved (&rest _ignore)
  669. "Reset all edited or set settings in the buffer to their saved value.
  670. This also shows the saved values in the buffer."
  671. (interactive)
  672. (custom-command-apply
  673. (lambda (widget)
  674. (if (memq (widget-get widget :custom-state) '(modified set changed rogue))
  675. (widget-apply widget :custom-reset-saved)))
  676. "Reset all settings (current values and buffer text) to saved values? "))
  677. ;; The next two variables are bound to '(t) by `Custom-reset-standard'
  678. ;; and `custom-group-reset-standard'. If these variables are nil, both
  679. ;; `custom-variable-reset-standard' and `custom-face-reset-standard'
  680. ;; save, reset and redraw the handled widget immediately. Otherwise,
  681. ;; they add the widget to the corresponding list and leave it to
  682. ;; `custom-reset-standard-save-and-update' to save, reset and redraw it.
  683. (defvar custom-reset-standard-variables-list nil)
  684. (defvar custom-reset-standard-faces-list nil)
  685. ;; The next function was excerpted from `custom-variable-reset-standard'
  686. ;; and `custom-face-reset-standard' and is used to avoid calling
  687. ;; `custom-save-all' repeatedly (and thus saving settings to file one by
  688. ;; one) when erasing all customizations.
  689. (defun custom-reset-standard-save-and-update ()
  690. "Save settings and redraw after erasing customizations."
  691. (when (or (and custom-reset-standard-variables-list
  692. (not (eq custom-reset-standard-variables-list '(t))))
  693. (and custom-reset-standard-faces-list
  694. (not (eq custom-reset-standard-faces-list '(t)))))
  695. ;; Save settings to file.
  696. (custom-save-all)
  697. ;; Set state of and redraw variables.
  698. (dolist (widget custom-reset-standard-variables-list)
  699. (unless (eq widget t)
  700. (widget-put widget :custom-state 'unknown)
  701. (custom-redraw widget)))
  702. ;; Set state of and redraw faces.
  703. (dolist (widget custom-reset-standard-faces-list)
  704. (unless (eq widget t)
  705. (let* ((symbol (widget-value widget))
  706. (child (car (widget-get widget :children)))
  707. (comment-widget (widget-get widget :comment-widget)))
  708. (put symbol 'face-comment nil)
  709. (widget-value-set child
  710. (custom-pre-filter-face-spec
  711. (list (list t (custom-face-attributes-get
  712. symbol nil)))))
  713. ;; This call manages the comment visibility
  714. (widget-value-set comment-widget "")
  715. (custom-face-state-set widget)
  716. (custom-redraw-magic widget))))))
  717. (defun Custom-reset-standard (&rest _ignore)
  718. "Erase all customizations (either current or saved) in current buffer.
  719. The immediate result is to restore them to their standard values.
  720. This operation eliminates any saved values for the group members,
  721. making them as if they had never been customized at all."
  722. (interactive)
  723. ;; Bind these temporarily.
  724. (let ((custom-reset-standard-variables-list '(t))
  725. (custom-reset-standard-faces-list '(t)))
  726. (if (custom-command-apply
  727. (lambda (widget)
  728. (and (or (null (widget-get widget :custom-standard-value))
  729. (widget-apply widget :custom-standard-value))
  730. (memq (widget-get widget :custom-state)
  731. '(modified set changed saved rogue))
  732. (widget-apply widget :custom-mark-to-reset-standard)))
  733. "The settings will revert to their default values, in this
  734. and future sessions. Really erase customizations? " t)
  735. (custom-reset-standard-save-and-update))))
  736. ;;; The Customize Commands
  737. (defun custom-prompt-variable (prompt-var prompt-val &optional comment)
  738. "Prompt for a variable and a value and return them as a list.
  739. PROMPT-VAR is the prompt for the variable, and PROMPT-VAL is the
  740. prompt for the value. The %s escape in PROMPT-VAL is replaced with
  741. the name of the variable.
  742. If the variable has a `variable-interactive' property, that is used as if
  743. it were the arg to `interactive' (which see) to interactively read the value.
  744. If the variable has a `custom-type' property, it must be a widget and the
  745. `:prompt-value' property of that widget will be used for reading the value.
  746. If the variable also has a `custom-get' property, that is used for finding
  747. the current value of the variable, otherwise `symbol-value' is used.
  748. If optional COMMENT argument is non-nil, also prompt for a comment and return
  749. it as the third element in the list."
  750. (let* ((var (read-variable prompt-var))
  751. (minibuffer-help-form '(describe-variable var))
  752. (val
  753. (let ((prop (get var 'variable-interactive))
  754. (type (get var 'custom-type))
  755. (prompt (format prompt-val var)))
  756. (unless (listp type)
  757. (setq type (list type)))
  758. (cond (prop
  759. ;; Use VAR's `variable-interactive' property
  760. ;; as an interactive spec for prompting.
  761. (call-interactively `(lambda (arg)
  762. (interactive ,prop)
  763. arg)))
  764. (type
  765. (widget-prompt-value type
  766. prompt
  767. (if (boundp var)
  768. (funcall
  769. (or (get var 'custom-get) 'symbol-value)
  770. var))
  771. (not (boundp var))))
  772. (t
  773. (eval-minibuffer prompt))))))
  774. (if comment
  775. (list var val
  776. (read-string "Comment: " (get var 'variable-comment)))
  777. (list var val))))
  778. ;;;###autoload
  779. (defun customize-set-value (variable value &optional comment)
  780. "Set VARIABLE to VALUE, and return VALUE. VALUE is a Lisp object.
  781. If VARIABLE has a `variable-interactive' property, that is used as if
  782. it were the arg to `interactive' (which see) to interactively read the value.
  783. If VARIABLE has a `custom-type' property, it must be a widget and the
  784. `:prompt-value' property of that widget will be used for reading the value.
  785. If given a prefix (or a COMMENT argument), also prompt for a comment."
  786. (interactive (custom-prompt-variable "Set variable: "
  787. "Set %s to value: "
  788. current-prefix-arg))
  789. (cond ((string= comment "")
  790. (put variable 'variable-comment nil))
  791. (comment
  792. (put variable 'variable-comment comment)))
  793. (set variable value))
  794. ;;;###autoload
  795. (defun customize-set-variable (variable value &optional comment)
  796. "Set the default for VARIABLE to VALUE, and return VALUE.
  797. VALUE is a Lisp object.
  798. If VARIABLE has a `custom-set' property, that is used for setting
  799. VARIABLE, otherwise `set-default' is used.
  800. If VARIABLE has a `variable-interactive' property, that is used as if
  801. it were the arg to `interactive' (which see) to interactively read the value.
  802. If VARIABLE has a `custom-type' property, it must be a widget and the
  803. `:prompt-value' property of that widget will be used for reading the value.
  804. If given a prefix (or a COMMENT argument), also prompt for a comment."
  805. (interactive (custom-prompt-variable "Set variable: "
  806. "Set customized value for %s to: "
  807. current-prefix-arg))
  808. (custom-load-symbol variable)
  809. (custom-push-theme 'theme-value variable 'user 'set (custom-quote value))
  810. (funcall (or (get variable 'custom-set) 'set-default) variable value)
  811. (put variable 'customized-value (list (custom-quote value)))
  812. (cond ((string= comment "")
  813. (put variable 'variable-comment nil)
  814. (put variable 'customized-variable-comment nil))
  815. (comment
  816. (put variable 'variable-comment comment)
  817. (put variable 'customized-variable-comment comment)))
  818. value)
  819. ;;;###autoload
  820. (defun customize-save-variable (variable value &optional comment)
  821. "Set the default for VARIABLE to VALUE, and save it for future sessions.
  822. Return VALUE.
  823. If VARIABLE has a `custom-set' property, that is used for setting
  824. VARIABLE, otherwise `set-default' is used.
  825. If VARIABLE has a `variable-interactive' property, that is used as if
  826. it were the arg to `interactive' (which see) to interactively read the value.
  827. If VARIABLE has a `custom-type' property, it must be a widget and the
  828. `:prompt-value' property of that widget will be used for reading the value.
  829. If given a prefix (or a COMMENT argument), also prompt for a comment."
  830. (interactive (custom-prompt-variable "Set and save variable: "
  831. "Set and save value for %s as: "
  832. current-prefix-arg))
  833. (funcall (or (get variable 'custom-set) 'set-default) variable value)
  834. (put variable 'saved-value (list (custom-quote value)))
  835. (custom-push-theme 'theme-value variable 'user 'set (custom-quote value))
  836. (cond ((string= comment "")
  837. (put variable 'variable-comment nil)
  838. (put variable 'saved-variable-comment nil))
  839. (comment
  840. (put variable 'variable-comment comment)
  841. (put variable 'saved-variable-comment comment)))
  842. (put variable 'customized-value nil)
  843. (put variable 'customized-variable-comment nil)
  844. (if (custom-file t)
  845. (custom-save-all)
  846. (message "Setting `%s' temporarily since \"emacs -q\" would overwrite customizations"
  847. variable)
  848. (set variable value))
  849. value)
  850. ;; Some parts of Emacs might prompt the user to save customizations,
  851. ;; during startup before customizations are loaded. This function
  852. ;; handles this corner case by avoiding calling `custom-save-variable'
  853. ;; too early, which could wipe out existing customizations.
  854. ;;;###autoload
  855. (defun customize-push-and-save (list-var elts)
  856. "Add ELTS to LIST-VAR and save for future sessions, safely.
  857. ELTS should be a list. This function adds each entry to the
  858. value of LIST-VAR using `add-to-list'.
  859. If Emacs is initialized, call `customize-save-variable' to save
  860. the resulting list value now. Otherwise, add an entry to
  861. `after-init-hook' to save it after initialization."
  862. (dolist (entry elts)
  863. (add-to-list list-var entry))
  864. (if after-init-time
  865. (let ((coding-system-for-read nil))
  866. (customize-save-variable list-var (eval list-var)))
  867. (add-hook 'after-init-hook
  868. (lambda ()
  869. (customize-push-and-save list-var elts)))))
  870. ;;;###autoload
  871. (defun customize ()
  872. "Select a customization buffer which you can use to set user options.
  873. User options are structured into \"groups\".
  874. Initially the top-level group `Emacs' and its immediate subgroups
  875. are shown; the contents of those subgroups are initially hidden."
  876. (interactive)
  877. (customize-group 'emacs))
  878. ;;;###autoload
  879. (defun customize-mode (mode)
  880. "Customize options related to a major or minor mode.
  881. By default the current major mode is used. With a prefix
  882. argument or if the current major mode has no known group, prompt
  883. for the MODE to customize."
  884. (interactive
  885. (list
  886. (let ((completion-regexp-list '("-mode\\'"))
  887. (group (custom-group-of-mode major-mode)))
  888. (if (and group (not current-prefix-arg))
  889. major-mode
  890. (intern
  891. (completing-read (if group
  892. (format "Mode (default %s): " major-mode)
  893. "Mode: ")
  894. obarray
  895. 'custom-group-of-mode
  896. t nil nil (if group (symbol-name major-mode))))))))
  897. (customize-group (custom-group-of-mode mode)))
  898. (defun customize-read-group ()
  899. (let ((completion-ignore-case t))
  900. (completing-read "Customize group (default emacs): "
  901. obarray
  902. (lambda (symbol)
  903. (or (and (get symbol 'custom-loads)
  904. (not (get symbol 'custom-autoload)))
  905. (get symbol 'custom-group)))
  906. t)))
  907. ;;;###autoload
  908. (defun customize-group (&optional group other-window)
  909. "Customize GROUP, which must be a customization group.
  910. If OTHER-WINDOW is non-nil, display in another window."
  911. (interactive (list (customize-read-group)))
  912. (when (stringp group)
  913. (if (string-equal "" group)
  914. (setq group 'emacs)
  915. (setq group (intern group))))
  916. (let ((name (format "*Customize Group: %s*"
  917. (custom-unlispify-tag-name group))))
  918. (cond
  919. ((null (get-buffer name))
  920. (funcall (if other-window
  921. 'custom-buffer-create-other-window
  922. 'custom-buffer-create)
  923. (list (list group 'custom-group))
  924. name
  925. (concat " for group "
  926. (custom-unlispify-tag-name group))))
  927. (other-window
  928. (switch-to-buffer-other-window name))
  929. (t
  930. (pop-to-buffer-same-window name)))))
  931. ;;;###autoload
  932. (defun customize-group-other-window (&optional group)
  933. "Customize GROUP, which must be a customization group, in another window."
  934. (interactive (list (customize-read-group)))
  935. (customize-group group t))
  936. ;;;###autoload
  937. (defalias 'customize-variable 'customize-option)
  938. ;;;###autoload
  939. (defun customize-option (symbol)
  940. "Customize SYMBOL, which must be a user option."
  941. (interactive (custom-variable-prompt))
  942. (unless symbol
  943. (error "No variable specified"))
  944. (let ((basevar (indirect-variable symbol)))
  945. (custom-buffer-create (list (list basevar 'custom-variable))
  946. (format "*Customize Option: %s*"
  947. (custom-unlispify-tag-name basevar)))
  948. (unless (eq symbol basevar)
  949. (message "`%s' is an alias for `%s'" symbol basevar))))
  950. ;;;###autoload
  951. (defalias 'customize-variable-other-window 'customize-option-other-window)
  952. ;;;###autoload
  953. (defun customize-option-other-window (symbol)
  954. "Customize SYMBOL, which must be a user option.
  955. Show the buffer in another window, but don't select it."
  956. (interactive (custom-variable-prompt))
  957. (unless symbol
  958. (error "No variable specified"))
  959. (let ((basevar (indirect-variable symbol)))
  960. (custom-buffer-create-other-window
  961. (list (list basevar 'custom-variable))
  962. (format "*Customize Option: %s*" (custom-unlispify-tag-name basevar)))
  963. (unless (eq symbol basevar)
  964. (message "`%s' is an alias for `%s'" symbol basevar))))
  965. (defvar customize-changed-options-previous-release "24.5"
  966. "Version for `customize-changed-options' to refer back to by default.")
  967. ;; Packages will update this variable, so make it available.
  968. ;;;###autoload
  969. (defvar customize-package-emacs-version-alist nil
  970. "Alist mapping versions of a package to Emacs versions.
  971. We use this for packages that have their own names, but are released
  972. as part of Emacs itself.
  973. Each elements looks like this:
  974. (PACKAGE (PVERSION . EVERSION)...)
  975. Here PACKAGE is the name of a package, as a symbol. After
  976. PACKAGE come one or more elements, each associating a
  977. package version PVERSION with the first Emacs version
  978. EVERSION in which it (or a subsequent version of PACKAGE)
  979. was first released. Both PVERSION and EVERSION are strings.
  980. PVERSION should be a string that this package used in
  981. the :package-version keyword for `defcustom', `defgroup',
  982. and `defface'.
  983. For example, the MH-E package updates this alist as follows:
  984. (add-to-list \\='customize-package-emacs-version-alist
  985. \\='(MH-E (\"6.0\" . \"22.1\") (\"6.1\" . \"22.1\")
  986. (\"7.0\" . \"22.1\") (\"7.1\" . \"22.1\")
  987. (\"7.2\" . \"22.1\") (\"7.3\" . \"22.1\")
  988. (\"7.4\" . \"22.1\") (\"8.0\" . \"22.1\")))
  989. The value of PACKAGE needs to be unique and it needs to match the
  990. PACKAGE value appearing in the :package-version keyword. Since
  991. the user might see the value in a error message, a good choice is
  992. the official name of the package, such as MH-E or Gnus.")
  993. ;;;###autoload
  994. (defalias 'customize-changed 'customize-changed-options)
  995. ;;;###autoload
  996. (defun customize-changed-options (&optional since-version)
  997. "Customize all settings whose meanings have changed in Emacs itself.
  998. This includes new user options and faces, and new customization
  999. groups, as well as older options and faces whose meanings or
  1000. default values have changed since the previous major Emacs
  1001. release.
  1002. With argument SINCE-VERSION (a string), customize all settings
  1003. that were added or redefined since that version."
  1004. (interactive
  1005. (list
  1006. (read-from-minibuffer
  1007. (format "Customize options changed, since version (default %s): "
  1008. customize-changed-options-previous-release))))
  1009. (if (equal since-version "")
  1010. (setq since-version nil)
  1011. (unless (condition-case nil
  1012. (numberp (read since-version))
  1013. (error nil))
  1014. (signal 'wrong-type-argument (list 'numberp since-version))))
  1015. (unless since-version
  1016. (setq since-version customize-changed-options-previous-release))
  1017. ;; Load the information for versions since since-version. We use
  1018. ;; custom-load-symbol for this.
  1019. (put 'custom-versions-load-alist 'custom-loads nil)
  1020. (dolist (elt custom-versions-load-alist)
  1021. (if (customize-version-lessp since-version (car elt))
  1022. (dolist (load (cdr elt))
  1023. (custom-add-load 'custom-versions-load-alist load))))
  1024. (custom-load-symbol 'custom-versions-load-alist)
  1025. (put 'custom-versions-load-alist 'custom-loads nil)
  1026. (let (found)
  1027. (mapatoms
  1028. (lambda (symbol)
  1029. (let* ((package-version (get symbol 'custom-package-version))
  1030. (version
  1031. (or (and package-version
  1032. (customize-package-emacs-version symbol
  1033. package-version))
  1034. (get symbol 'custom-version))))
  1035. (if version
  1036. (when (customize-version-lessp since-version version)
  1037. (if (or (get symbol 'custom-group)
  1038. (get symbol 'group-documentation))
  1039. (push (list symbol 'custom-group) found))
  1040. (if (custom-variable-p symbol)
  1041. (push (list symbol 'custom-variable) found))
  1042. (if (custom-facep symbol)
  1043. (push (list symbol 'custom-face) found)))))))
  1044. (if found
  1045. (custom-buffer-create (custom-sort-items found t 'first)
  1046. "*Customize Changed Options*")
  1047. (user-error "No user option defaults have been changed since Emacs %s"
  1048. since-version))))
  1049. (defun customize-package-emacs-version (symbol package-version)
  1050. "Return the Emacs version in which SYMBOL's meaning last changed.
  1051. PACKAGE-VERSION has the form (PACKAGE . VERSION). We use
  1052. `customize-package-emacs-version-alist' to find the version of
  1053. Emacs that is associated with version VERSION of PACKAGE."
  1054. (let (package-versions emacs-version)
  1055. ;; Use message instead of error since we want user to be able to
  1056. ;; see the rest of the symbols even if a package author has
  1057. ;; botched things up.
  1058. (cond ((not (listp package-version))
  1059. (message "Invalid package-version value for %s" symbol))
  1060. ((setq package-versions (assq (car package-version)
  1061. customize-package-emacs-version-alist))
  1062. (setq emacs-version
  1063. (cdr (assoc (cdr package-version) package-versions)))
  1064. (unless emacs-version
  1065. (message "%s version %s not found in %s" symbol
  1066. (cdr package-version)
  1067. "customize-package-emacs-version-alist")))
  1068. (t
  1069. (message "Package %s version %s lists no corresponding Emacs version"
  1070. (car package-version)
  1071. (cdr package-version))))
  1072. emacs-version))
  1073. (defun customize-version-lessp (version1 version2)
  1074. ;; Why are the versions strings, and given that they are, why aren't
  1075. ;; they converted to numbers and compared as such here? -- fx
  1076. ;; In case someone made a mistake and left out the quotes
  1077. ;; in the :version value.
  1078. (if (numberp version2)
  1079. (setq version2 (prin1-to-string version2)))
  1080. (let (major1 major2 minor1 minor2)
  1081. (string-match "\\([0-9]+\\)\\(\\.\\([0-9]+\\)\\)?" version1)
  1082. (setq major1 (read (or (match-string 1 version1)
  1083. "0")))
  1084. (setq minor1 (read (or (match-string 3 version1)
  1085. "0")))
  1086. (string-match "\\([0-9]+\\)\\(\\.\\([0-9]+\\)\\)?" version2)
  1087. (setq major2 (read (or (match-string 1 version2)
  1088. "0")))
  1089. (setq minor2 (read (or (match-string 3 version2)
  1090. "0")))
  1091. (or (< major1 major2)
  1092. (and (= major1 major2)
  1093. (< minor1 minor2)))))
  1094. ;;;###autoload
  1095. (defun customize-face (&optional face other-window)
  1096. "Customize FACE, which should be a face name or nil.
  1097. If FACE is nil, customize all faces. If FACE is actually a
  1098. face-alias, customize the face it is aliased to.
  1099. If OTHER-WINDOW is non-nil, display in another window.
  1100. Interactively, when point is on text which has a face specified,
  1101. suggest to customize that face, if it's customizable."
  1102. (interactive (list (read-face-name "Customize face"
  1103. (or (face-at-point t t) "all faces") t)))
  1104. (if (member face '(nil ""))
  1105. (setq face (face-list)))
  1106. (if (and (listp face) (null (cdr face)))
  1107. (setq face (car face)))
  1108. (let ((display-fun (if other-window
  1109. 'custom-buffer-create-other-window
  1110. 'custom-buffer-create)))
  1111. (if (listp face)
  1112. (funcall display-fun
  1113. (custom-sort-items
  1114. (mapcar (lambda (s) (list s 'custom-face)) face)
  1115. t nil)
  1116. "*Customize Faces*")
  1117. ;; If FACE is actually an alias, customize the face it is aliased to.
  1118. (if (get face 'face-alias)
  1119. (setq face (get face 'face-alias)))
  1120. (unless (facep face)
  1121. (error "Invalid face %S" face))
  1122. (funcall display-fun
  1123. (list (list face 'custom-face))
  1124. (format "*Customize Face: %s*"
  1125. (custom-unlispify-tag-name face))))))
  1126. ;;;###autoload
  1127. (defun customize-face-other-window (&optional face)
  1128. "Show customization buffer for face FACE in other window.
  1129. If FACE is actually a face-alias, customize the face it is aliased to.
  1130. Interactively, when point is on text which has a face specified,
  1131. suggest to customize that face, if it's customizable."
  1132. (interactive (list (read-face-name "Customize face"
  1133. (or (face-at-point t t) "all faces") t)))
  1134. (customize-face face t))
  1135. (defun custom-unsaved-options ()
  1136. "List of options and faces set in this session but not saved.
  1137. Each entry is of the form (SYMBOL TYPE), where TYPE is one of the
  1138. symbols `custom-face' or `custom-variable'."
  1139. (let ((found nil))
  1140. (mapatoms (lambda (symbol)
  1141. (and (or (get symbol 'customized-face)
  1142. (get symbol 'customized-face-comment))
  1143. (custom-facep symbol)
  1144. (push (list symbol 'custom-face) found))
  1145. (and (or (get symbol 'customized-value)
  1146. (get symbol 'customized-variable-comment))
  1147. (boundp symbol)
  1148. (push (list symbol 'custom-variable) found))))
  1149. found))
  1150. (defalias 'customize-customized 'customize-unsaved)
  1151. ;;;###autoload
  1152. (defun customize-unsaved ()
  1153. "Customize all options and faces set in this session but not saved."
  1154. (interactive)
  1155. (let ((found (custom-unsaved-options)))
  1156. (if (not found)
  1157. (error "No user options are set but unsaved")
  1158. (custom-buffer-create (custom-sort-items found t nil)
  1159. "*Customize Unsaved*"))))
  1160. ;;;###autoload
  1161. (defun customize-rogue ()
  1162. "Customize all user variables modified outside customize."
  1163. (interactive)
  1164. (let ((found nil))
  1165. (mapatoms (lambda (symbol)
  1166. (let ((cval (or (get symbol 'customized-value)
  1167. (get symbol 'saved-value)
  1168. (get symbol 'standard-value))))
  1169. (when (and cval ;Declared with defcustom.
  1170. (default-boundp symbol) ;Has a value.
  1171. (not (equal (eval (car cval))
  1172. ;; Which does not match customize.
  1173. (default-value symbol))))
  1174. (push (list symbol 'custom-variable) found)))))
  1175. (if (not found)
  1176. (user-error "No rogue user options")
  1177. (custom-buffer-create (custom-sort-items found t nil)
  1178. "*Customize Rogue*"))))
  1179. ;;;###autoload
  1180. (defun customize-saved ()
  1181. "Customize all saved options and faces."
  1182. (interactive)
  1183. (let ((found nil))
  1184. (mapatoms (lambda (symbol)
  1185. (and (or (get symbol 'saved-face)
  1186. (get symbol 'saved-face-comment))
  1187. (custom-facep symbol)
  1188. (push (list symbol 'custom-face) found))
  1189. (and (or (get symbol 'saved-value)
  1190. (get symbol 'saved-variable-comment))
  1191. (boundp symbol)
  1192. (push (list symbol 'custom-variable) found))))
  1193. (if (not found)
  1194. (user-error "No saved user options")
  1195. (custom-buffer-create (custom-sort-items found t nil)
  1196. "*Customize Saved*"))))
  1197. (declare-function apropos-parse-pattern "apropos" (pattern))
  1198. (defvar apropos-regexp)
  1199. ;;;###autoload
  1200. (defun customize-apropos (pattern &optional type)
  1201. "Customize loaded options, faces and groups matching PATTERN.
  1202. PATTERN can be a word, a list of words (separated by spaces),
  1203. or a regexp (using some regexp special characters). If it is a word,
  1204. search for matches for that word as a substring. If it is a list of
  1205. words, search for matches for any two (or more) of those words.
  1206. If TYPE is `options', include only options.
  1207. If TYPE is `faces', include only faces.
  1208. If TYPE is `groups', include only groups."
  1209. (interactive (list (apropos-read-pattern "symbol") nil))
  1210. (require 'apropos)
  1211. (unless (memq type '(nil options faces groups))
  1212. (error "Invalid setting type %s" (symbol-name type)))
  1213. (apropos-parse-pattern pattern) ;Sets apropos-regexp by side-effect: Yuck!
  1214. (let (found)
  1215. (mapatoms
  1216. (lambda (symbol)
  1217. (when (string-match-p apropos-regexp (symbol-name symbol))
  1218. (if (memq type '(nil groups))
  1219. (if (get symbol 'custom-group)
  1220. (push (list symbol 'custom-group) found)))
  1221. (if (memq type '(nil faces))
  1222. (if (custom-facep symbol)
  1223. (push (list symbol 'custom-face) found)))
  1224. (if (memq type '(nil options))
  1225. (if (and (boundp symbol)
  1226. (eq (indirect-variable symbol) symbol)
  1227. (or (get symbol 'saved-value)
  1228. (custom-variable-p symbol)))
  1229. (push (list symbol 'custom-variable) found))))))
  1230. (unless found
  1231. (error "No customizable %s matching %s" (if (not type)
  1232. "group, face, or option"
  1233. (symbol-name type))
  1234. pattern))
  1235. (custom-buffer-create
  1236. (custom-sort-items found t custom-buffer-order-groups)
  1237. "*Customize Apropos*")))
  1238. ;;;###autoload
  1239. (defun customize-apropos-options (regexp &optional ignored)
  1240. "Customize all loaded customizable options matching REGEXP."
  1241. (interactive (list (apropos-read-pattern "options")))
  1242. (customize-apropos regexp 'options))
  1243. ;;;###autoload
  1244. (defun customize-apropos-faces (regexp)
  1245. "Customize all loaded faces matching REGEXP."
  1246. (interactive (list (apropos-read-pattern "faces")))
  1247. (customize-apropos regexp 'faces))
  1248. ;;;###autoload
  1249. (defun customize-apropos-groups (regexp)
  1250. "Customize all loaded groups matching REGEXP."
  1251. (interactive (list (apropos-read-pattern "groups")))
  1252. (customize-apropos regexp 'groups))
  1253. ;;;###autoload
  1254. (defun custom-prompt-customize-unsaved-options ()
  1255. "Prompt user to customize any unsaved customization options.
  1256. Return non-nil if user chooses to customize, for use in
  1257. `kill-emacs-query-functions'."
  1258. (not (and (custom-unsaved-options)
  1259. (yes-or-no-p "Some customized options have not been saved; Examine? ")
  1260. (customize-unsaved)
  1261. t)))
  1262. ;;; Buffer.
  1263. (defcustom custom-buffer-style 'links
  1264. "Control the presentation style for customization buffers.
  1265. The value should be a symbol, one of:
  1266. `brackets': groups nest within each other with big horizontal brackets.
  1267. `links': groups have links to subgroups.
  1268. `tree': display groups as trees."
  1269. :type '(radio (const brackets)
  1270. (const links)
  1271. (const tree))
  1272. :group 'custom-buffer)
  1273. (defcustom custom-buffer-done-kill nil
  1274. "Non-nil means exiting a Custom buffer should kill it."
  1275. :type 'boolean
  1276. :version "22.1"
  1277. :group 'custom-buffer)
  1278. (defcustom custom-buffer-indent 3
  1279. "Number of spaces to indent nested groups."
  1280. :type 'integer
  1281. :group 'custom-buffer)
  1282. (defun custom-get-fresh-buffer (name)
  1283. "Get a fresh new buffer with name NAME.
  1284. If the buffer already exist, clean it up to be like new.
  1285. Beware: it's not quite like new. Good enough for custom, but maybe
  1286. not for everybody."
  1287. ;; To be more complete, we should also kill all permanent-local variables,
  1288. ;; but it's not needed for custom.
  1289. (let ((buf (get-buffer name)))
  1290. (when (and buf (buffer-local-value 'buffer-file-name buf))
  1291. ;; This will check if the file is not saved.
  1292. (kill-buffer buf)
  1293. (setq buf nil))
  1294. (if (null buf)
  1295. (get-buffer-create name)
  1296. (with-current-buffer buf
  1297. (kill-all-local-variables)
  1298. (run-hooks 'kill-buffer-hook)
  1299. ;; Delete overlays before erasing the buffer so the overlay hooks
  1300. ;; don't get run spuriously when we erase the buffer.
  1301. (let ((ols (overlay-lists)))
  1302. (dolist (ol (nconc (car ols) (cdr ols)))
  1303. (delete-overlay ol)))
  1304. (erase-buffer)
  1305. buf))))
  1306. ;;;###autoload
  1307. (defun custom-buffer-create (options &optional name _description)
  1308. "Create a buffer containing OPTIONS.
  1309. Optional NAME is the name of the buffer.
  1310. OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
  1311. SYMBOL is a customization option, and WIDGET is a widget for editing
  1312. that option.
  1313. DESCRIPTION is unused."
  1314. (pop-to-buffer-same-window
  1315. (custom-get-fresh-buffer (or name "*Customization*")))
  1316. (custom-buffer-create-internal options))
  1317. ;;;###autoload
  1318. (defun custom-buffer-create-other-window (options &optional name _description)
  1319. "Create a buffer containing OPTIONS, and display it in another window.
  1320. The result includes selecting that window.
  1321. Optional NAME is the name of the buffer.
  1322. OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where
  1323. SYMBOL is a customization option, and WIDGET is a widget for editing
  1324. that option.
  1325. DESCRIPTION is unused."
  1326. (unless name (setq name "*Customization*"))
  1327. (switch-to-buffer-other-window (custom-get-fresh-buffer name))
  1328. (custom-buffer-create-internal options))
  1329. (defcustom custom-reset-button-menu t
  1330. "If non-nil, only show a single reset button in customize buffers.
  1331. This button will have a menu with all three reset operations."
  1332. :type 'boolean
  1333. :group 'custom-buffer
  1334. :version "24.3")
  1335. (defcustom custom-buffer-verbose-help t
  1336. "If non-nil, include explanatory text in the customization buffer."
  1337. :type 'boolean
  1338. :group 'custom-buffer)
  1339. (defun Custom-buffer-done (&rest _ignore)
  1340. "Exit current Custom buffer according to `custom-buffer-done-kill'."
  1341. (interactive)
  1342. (quit-window custom-buffer-done-kill))
  1343. (defvar custom-button nil
  1344. "Face used for buttons in customization buffers.")
  1345. (defvar custom-button-mouse nil
  1346. "Mouse face used for buttons in customization buffers.")
  1347. (defvar custom-button-pressed nil
  1348. "Face used for pressed buttons in customization buffers.")
  1349. (defcustom custom-search-field t
  1350. "If non-nil, show a search field in Custom buffers."
  1351. :type 'boolean
  1352. :version "24.1"
  1353. :group 'custom-buffer)
  1354. (defcustom custom-raised-buttons (not (equal (face-valid-attribute-values :box)
  1355. '(("unspecified" . unspecified))))
  1356. "If non-nil, indicate active buttons in a raised-button style.
  1357. Otherwise use brackets."
  1358. :type 'boolean
  1359. :version "21.1"
  1360. :group 'custom-buffer
  1361. :set (lambda (variable value)
  1362. (custom-set-default variable value)
  1363. (setq custom-button
  1364. (if value 'custom-button 'custom-button-unraised))
  1365. (setq custom-button-mouse
  1366. (if value 'custom-button-mouse 'highlight))
  1367. (setq custom-button-pressed
  1368. (if value
  1369. 'custom-button-pressed
  1370. 'custom-button-pressed-unraised))))
  1371. (defun custom-buffer-create-internal (options &optional _description)
  1372. (Custom-mode)
  1373. (let ((init-file (or custom-file user-init-file)))
  1374. ;; Insert verbose help at the top of the custom buffer.
  1375. (when custom-buffer-verbose-help
  1376. (unless init-file
  1377. (widget-insert
  1378. (format-message
  1379. "Custom settings cannot be saved; maybe you started Emacs with `-q'.\n")))
  1380. (widget-insert "For help using this buffer, see ")
  1381. (widget-create 'custom-manual
  1382. :tag "Easy Customization"
  1383. "(emacs)Easy Customization")
  1384. (widget-insert " in the ")
  1385. (widget-create 'custom-manual
  1386. :tag "Emacs manual"
  1387. :help-echo "Read the Emacs manual."
  1388. "(emacs)Top")
  1389. (widget-insert "."))
  1390. (widget-insert "\n")
  1391. ;; Insert the search field.
  1392. (when custom-search-field
  1393. (widget-insert "\n")
  1394. (let* ((echo "Search for custom items.
  1395. You can enter one or more words separated by spaces,
  1396. or a regular expression.")
  1397. (search-widget
  1398. (widget-create
  1399. 'editable-field
  1400. :size 40 :help-echo echo
  1401. :action (lambda (widget &optional _event)
  1402. (customize-apropos (split-string (widget-value widget)))))))
  1403. (widget-insert " ")
  1404. (widget-create-child-and-convert
  1405. search-widget 'push-button
  1406. :tag " Search "
  1407. :help-echo echo :action
  1408. (lambda (widget &optional _event)
  1409. (customize-apropos (split-string (widget-value (widget-get widget :parent))))))
  1410. (widget-insert "\n")))
  1411. ;; The custom command buttons are also in the toolbar, so for a
  1412. ;; time they were not inserted in the buffer if the toolbar was in use.
  1413. ;; But it can be a little confusing for the buffer layout to
  1414. ;; change according to whether or nor the toolbar is on, not to
  1415. ;; mention that a custom buffer can in theory be created in a
  1416. ;; frame with a toolbar, then later viewed in one without.
  1417. ;; So now the buttons are always inserted in the buffer. (Bug#1326)
  1418. (if custom-buffer-verbose-help
  1419. (widget-insert "
  1420. Operate on all settings in this buffer:\n"))
  1421. (let ((button (lambda (tag action active help _icon _label)
  1422. (widget-insert " ")
  1423. (if (eval active)
  1424. (widget-create 'push-button :tag tag
  1425. :help-echo help :action action))))
  1426. (commands custom-commands))
  1427. (if custom-reset-button-menu
  1428. (progn
  1429. (widget-create 'push-button
  1430. :tag " Revert... "
  1431. :help-echo "Show a menu with reset operations."
  1432. :mouse-down-action 'ignore
  1433. :action 'custom-reset)
  1434. (apply button (pop commands)) ; Apply
  1435. (apply button (pop commands))) ; Apply and Save
  1436. (apply button (pop commands)) ; Apply
  1437. (apply button (pop commands)) ; Apply and Save
  1438. (widget-insert "\n")
  1439. (apply button (pop commands)) ; Undo
  1440. (apply button (pop commands)) ; Reset
  1441. (apply button (pop commands)) ; Erase
  1442. (widget-insert " ")
  1443. (pop commands) ; Help (omitted)
  1444. (apply button (pop commands)))) ; Exit
  1445. (widget-insert "\n\n"))
  1446. ;; Now populate the custom buffer.
  1447. (message "Creating customization items...")
  1448. (buffer-disable-undo)
  1449. (setq custom-options
  1450. (if (= (length options) 1)
  1451. (mapcar (lambda (entry)
  1452. (widget-create (nth 1 entry)
  1453. :documentation-shown t
  1454. :custom-state 'unknown
  1455. :tag (custom-unlispify-tag-name
  1456. (nth 0 entry))
  1457. :value (nth 0 entry)))
  1458. options)
  1459. (let ((count 0)
  1460. (length (length options)))
  1461. (mapcar (lambda (entry)
  1462. (prog2
  1463. (message "Creating customization items ...%2d%%"
  1464. (floor (* 100.0 count) length))
  1465. (widget-create (nth 1 entry)
  1466. :tag (custom-unlispify-tag-name
  1467. (nth 0 entry))
  1468. :value (nth 0 entry))
  1469. (setq count (1+ count))
  1470. (unless (eq (preceding-char) ?\n)
  1471. (widget-insert "\n"))
  1472. (widget-insert "\n")))
  1473. options))))
  1474. (unless (eq (preceding-char) ?\n)
  1475. (widget-insert "\n"))
  1476. (message "Creating customization items ...done")
  1477. (message "Resetting customization items...")
  1478. (unless (eq custom-buffer-style 'tree)
  1479. (mapc 'custom-magic-reset custom-options))
  1480. (message "Resetting customization items...done")
  1481. (message "Creating customization setup...")
  1482. (widget-setup)
  1483. (buffer-enable-undo)
  1484. (goto-char (point-min))
  1485. (message "Creating customization setup...done"))
  1486. ;;; The Tree Browser.
  1487. ;;;###autoload
  1488. (defun customize-browse (&optional group)
  1489. "Create a tree browser for the customize hierarchy."
  1490. (interactive)
  1491. (unless group
  1492. (setq group 'emacs))
  1493. (let ((name "*Customize Browser*"))
  1494. (pop-to-buffer-same-window (custom-get-fresh-buffer name)))
  1495. (Custom-mode)
  1496. (widget-insert (format "\
  1497. %s buttons; type RET or click mouse-1
  1498. on a button to invoke its action.
  1499. Invoke [+] to expand a group, and [-] to collapse an expanded group.\n"
  1500. (if custom-raised-buttons
  1501. "Raised text indicates"
  1502. "Square brackets indicate")))
  1503. (if custom-browse-only-groups
  1504. (widget-insert "\
  1505. Invoke the [Group] button below to edit that item in another window.\n\n")
  1506. (widget-insert "Invoke the ")
  1507. (widget-create 'item
  1508. :format "%t"
  1509. :tag "[Group]"
  1510. :tag-glyph "folder")
  1511. (widget-insert ", ")
  1512. (widget-create 'item
  1513. :format "%t"
  1514. :tag "[Face]"
  1515. :tag-glyph "face")
  1516. (widget-insert ", and ")
  1517. (widget-create 'item
  1518. :format "%t"
  1519. :tag "[Option]"
  1520. :tag-glyph "option")
  1521. (widget-insert " buttons below to edit that
  1522. item in another window.\n\n"))
  1523. (let ((custom-buffer-style 'tree))
  1524. (widget-create 'custom-group
  1525. :custom-last t
  1526. :custom-state 'unknown
  1527. :tag (custom-unlispify-tag-name group)
  1528. :value group))
  1529. (widget-setup)
  1530. (goto-char (point-min)))
  1531. (define-widget 'custom-browse-visibility 'item
  1532. "Control visibility of items in the customize tree browser."
  1533. :format "%[[%t]%]"
  1534. :action 'custom-browse-visibility-action)
  1535. (defun custom-browse-visibility-action (widget &rest _ignore)
  1536. (let ((custom-buffer-style 'tree))
  1537. (custom-toggle-parent widget)))
  1538. (define-widget 'custom-browse-group-tag 'custom-group-link
  1539. "Show parent in other window when activated."
  1540. :tag "Group"
  1541. :tag-glyph "folder"
  1542. :action 'custom-browse-group-tag-action)
  1543. (defun custom-browse-group-tag-action (widget &rest _ignore)
  1544. (let ((parent (widget-get widget :parent)))
  1545. (customize-group-other-window (widget-value parent))))
  1546. (define-widget 'custom-browse-variable-tag 'custom-group-link
  1547. "Show parent in other window when activated."
  1548. :tag "Option"
  1549. :tag-glyph "option"
  1550. :action 'custom-browse-variable-tag-action)
  1551. (defun custom-browse-variable-tag-action (widget &rest _ignore)
  1552. (let ((parent (widget-get widget :parent)))
  1553. (customize-variable-other-window (widget-value parent))))
  1554. (define-widget 'custom-browse-face-tag 'custom-group-link
  1555. "Show parent in other window when activated."
  1556. :tag "Face"
  1557. :tag-glyph "face"
  1558. :action 'custom-browse-face-tag-action)
  1559. (defun custom-browse-face-tag-action (widget &rest _ignore)
  1560. (let ((parent (widget-get widget :parent)))
  1561. (customize-face-other-window (widget-value parent))))
  1562. (defconst custom-browse-alist '((" " "space")
  1563. (" | " "vertical")
  1564. ("-\\ " "top")
  1565. (" |-" "middle")
  1566. (" `-" "bottom")))
  1567. (defun custom-browse-insert-prefix (prefix)
  1568. "Insert PREFIX. On XEmacs convert it to line graphics."
  1569. ;; Fixme: do graphics.
  1570. (if nil ; (featurep 'xemacs)
  1571. (progn
  1572. (insert "*")
  1573. (while (not (string-equal prefix ""))
  1574. (let ((entry (substring prefix 0 3)))
  1575. (setq prefix (substring prefix 3))
  1576. (let ((overlay (make-overlay (1- (point)) (point) nil t nil))
  1577. (name (nth 1 (assoc entry custom-browse-alist))))
  1578. (overlay-put overlay 'end-glyph (widget-glyph-find name entry))
  1579. (overlay-put overlay 'start-open t)
  1580. (overlay-put overlay 'end-open t)))))
  1581. (insert prefix)))
  1582. ;;; Modification of Basic Widgets.
  1583. ;;
  1584. ;; We add extra properties to the basic widgets needed here. This is
  1585. ;; fine, as long as we are careful to stay within our own namespace.
  1586. ;;
  1587. ;; We want simple widgets to be displayed by default, but complex
  1588. ;; widgets to be hidden.
  1589. ;; This widget type is obsolete as of Emacs 24.1.
  1590. (widget-put (get 'item 'widget-type) :custom-show t)
  1591. (widget-put (get 'editable-field 'widget-type)
  1592. :custom-show (lambda (_widget value)
  1593. (let ((pp (pp-to-string value)))
  1594. (cond ((string-match-p "\n" pp)
  1595. nil)
  1596. ((> (length pp) 40)
  1597. nil)
  1598. (t t)))))
  1599. (widget-put (get 'menu-choice 'widget-type) :custom-show t)
  1600. ;;; The `custom-manual' Widget.
  1601. (define-widget 'custom-manual 'info-link
  1602. "Link to the manual entry for this customization option."
  1603. :help-echo "Read the manual entry for this option."
  1604. :keymap custom-mode-link-map
  1605. :follow-link 'mouse-face
  1606. :button-face 'custom-link
  1607. :mouse-face 'highlight
  1608. :pressed-face 'highlight
  1609. :tag "Manual")
  1610. ;;; The `custom-magic' Widget.
  1611. (defgroup custom-magic-faces nil
  1612. "Faces used by the magic button."
  1613. :group 'custom-faces
  1614. :group 'custom-buffer)
  1615. (defface custom-invalid '((((class color))
  1616. :foreground "yellow1" :background "red1")
  1617. (t :weight bold :slant italic :underline t))
  1618. "Face used when the customize item is invalid."
  1619. :group 'custom-magic-faces)
  1620. (defface custom-rogue '((((class color))
  1621. :foreground "pink" :background "black")
  1622. (t :underline t))
  1623. "Face used when the customize item is not defined for customization."
  1624. :group 'custom-magic-faces)
  1625. (defface custom-modified '((((min-colors 88) (class color))
  1626. :foreground "white" :background "blue1")
  1627. (((class color))
  1628. :foreground "white" :background "blue")
  1629. (t :slant italic))
  1630. "Face used when the customize item has been modified."
  1631. :group 'custom-magic-faces)
  1632. (defface custom-set '((((min-colors 88) (class color))
  1633. :foreground "blue1" :background "white")
  1634. (((class color))
  1635. :foreground "blue" :background "white")
  1636. (t :slant italic))
  1637. "Face used when the customize item has been set."
  1638. :group 'custom-magic-faces)
  1639. (defface custom-changed '((((min-colors 88) (class color))
  1640. :foreground "white" :background "blue1")
  1641. (((class color))
  1642. :foreground "white" :background "blue")
  1643. (t :slant italic))
  1644. "Face used when the customize item has been changed."
  1645. :group 'custom-magic-faces)
  1646. (defface custom-themed '((((min-colors 88) (class color))
  1647. :foreground "white" :background "blue1")
  1648. (((class color))
  1649. :foreground "white" :background "blue")
  1650. (t :slant italic))
  1651. "Face used when the customize item has been set by a theme."
  1652. :group 'custom-magic-faces)
  1653. (defface custom-saved '((t :underline t))
  1654. "Face used when the customize item has been saved."
  1655. :group 'custom-magic-faces)
  1656. (defconst custom-magic-alist
  1657. '((nil "#" underline "\
  1658. UNINITIALIZED, you should not see this.")
  1659. (unknown "?" italic "\
  1660. UNKNOWN, you should not see this.")
  1661. (hidden "-" default "\
  1662. HIDDEN, invoke \"Show\" in the previous line to show." "\
  1663. group now hidden, invoke \"Show\", above, to show contents.")
  1664. (invalid "x" custom-invalid "\
  1665. INVALID, the displayed value cannot be set.")
  1666. (modified "*" custom-modified "\
  1667. EDITED, shown value does not take effect until you set or save it." "\
  1668. something in this group has been edited but not set.")
  1669. (set "+" custom-set "\
  1670. SET for current session only." "\
  1671. something in this group has been set but not saved.")
  1672. (changed ":" custom-changed "\
  1673. CHANGED outside Customize." "\
  1674. something in this group has been changed outside customize.")
  1675. (saved "!" custom-saved "\
  1676. SAVED and set." "\
  1677. something in this group has been set and saved.")
  1678. (themed "o" custom-themed "\
  1679. THEMED." "\
  1680. visible group members are set by enabled themes.")
  1681. (rogue "@" custom-rogue "\
  1682. NO CUSTOMIZATION DATA; not intended to be customized." "\
  1683. something in this group is not prepared for customization.")
  1684. (standard " " nil "\
  1685. STANDARD." "\
  1686. visible group members are all at standard values."))
  1687. "Alist of customize option states.
  1688. Each entry is of the form (STATE MAGIC FACE ITEM-DESC [ GROUP-DESC ]), where
  1689. STATE is one of the following symbols:
  1690. nil
  1691. For internal use, should never occur.
  1692. `unknown'
  1693. For internal use, should never occur.
  1694. `hidden'
  1695. This item is not being displayed.
  1696. `invalid'
  1697. This item is modified, but has an invalid form.
  1698. `modified'
  1699. This item is modified, and has a valid form.
  1700. `set'
  1701. This item has been set but not saved.
  1702. `changed'
  1703. The current value of this item has been changed outside Customize.
  1704. `saved'
  1705. This item is marked for saving.
  1706. `rogue'
  1707. This item has no customization information.
  1708. `themed'
  1709. This item was set by an enabled Custom theme.
  1710. `standard'
  1711. This item is unchanged from the standard setting.
  1712. MAGIC is a string used to present that state.
  1713. FACE is a face used to present the state.
  1714. ITEM-DESC is a string describing the state for options.
  1715. GROUP-DESC is a string describing the state for groups. If this is
  1716. left out, ITEM-DESC will be used.
  1717. The string %c in either description will be replaced with the
  1718. category of the item. These are `group', `option', and `face'.
  1719. The list should be sorted most significant first.")
  1720. (defcustom custom-magic-show 'long
  1721. "If non-nil, show textual description of the state.
  1722. If `long', show a full-line description, not just one word."
  1723. :type '(choice (const :tag "no" nil)
  1724. (const long)
  1725. (other :tag "short" short))
  1726. :group 'custom-buffer)
  1727. (defcustom custom-magic-show-hidden '(option face)
  1728. "Control whether the State button is shown for hidden items.
  1729. The value should be a list with the custom categories where the State
  1730. button should be visible. Possible categories are `group', `option',
  1731. and `face'."
  1732. :type '(set (const group) (const option) (const face))
  1733. :group 'custom-buffer)
  1734. (defcustom custom-magic-show-button nil
  1735. "Show a \"magic\" button indicating the state of each customization option."
  1736. :type 'boolean
  1737. :group 'custom-buffer)
  1738. (define-widget 'custom-magic 'default
  1739. "Show and manipulate state for a customization option."
  1740. :format "%v"
  1741. :action 'widget-parent-action
  1742. :notify 'ignore
  1743. :value-get 'ignore
  1744. :value-create 'custom-magic-value-create
  1745. :value-delete 'widget-children-value-delete)
  1746. (defun widget-magic-mouse-down-action (widget &optional _event)
  1747. ;; Non-nil unless hidden.
  1748. (not (eq (widget-get (widget-get (widget-get widget :parent) :parent)
  1749. :custom-state)
  1750. 'hidden)))
  1751. (defun custom-magic-value-create (widget)
  1752. "Create compact status report for WIDGET."
  1753. (let* ((parent (widget-get widget :parent))
  1754. (state (widget-get parent :custom-state))
  1755. (hidden (eq state 'hidden))
  1756. (entry (assq state custom-magic-alist))
  1757. (magic (nth 1 entry))
  1758. (face (nth 2 entry))
  1759. (category (widget-get parent :custom-category))
  1760. (text (or (and (eq category 'group)
  1761. (nth 4 entry))
  1762. (nth 3 entry)))
  1763. (form (widget-get parent :custom-form))
  1764. children)
  1765. (unless (eq state 'hidden)
  1766. (while (string-match "\\`\\(.*\\)%c\\(.*\\)\\'" text)
  1767. (setq text (concat (match-string 1 text)
  1768. (symbol-name category)
  1769. (match-string 2 text))))
  1770. (when (and custom-magic-show
  1771. (or (not hidden)
  1772. (memq category custom-magic-show-hidden)))
  1773. (insert " ")
  1774. (when (and (eq category 'group)
  1775. (not (and (eq custom-buffer-style 'links)
  1776. (> (widget-get parent :custom-level) 1))))
  1777. (insert-char ?\s (* custom-buffer-indent
  1778. (widget-get parent :custom-level))))
  1779. (push (widget-create-child-and-convert
  1780. widget 'choice-item
  1781. :help-echo "Change the state of this item."
  1782. :format (if hidden "%t" "%[%t%]")
  1783. :button-prefix 'widget-push-button-prefix
  1784. :button-suffix 'widget-push-button-suffix
  1785. :mouse-down-action 'widget-magic-mouse-down-action
  1786. :tag " State ")
  1787. children)
  1788. (insert ": ")
  1789. (let ((start (point)))
  1790. (if (eq custom-magic-show 'long)
  1791. (insert text)
  1792. (insert (symbol-name state)))
  1793. (cond ((eq form 'lisp)
  1794. (insert " (lisp)"))
  1795. ((eq form 'mismatch)
  1796. (insert " (mismatch)")))
  1797. (put-text-property start (point) 'face 'custom-state))
  1798. (insert "\n"))
  1799. (when (and (eq category 'group)
  1800. (not (and (eq custom-buffer-style 'links)
  1801. (> (widget-get parent :custom-level) 1))))
  1802. (insert-char ?\s (* custom-buffer-indent
  1803. (widget-get parent :custom-level))))
  1804. (when custom-magic-show-button
  1805. (when custom-magic-show
  1806. (let ((indent (widget-get parent :indent)))
  1807. (when indent
  1808. (insert-char ? indent))))
  1809. (push (widget-create-child-and-convert
  1810. widget 'choice-item
  1811. :mouse-down-action 'widget-magic-mouse-down-action
  1812. :button-face face
  1813. :button-prefix ""
  1814. :button-suffix ""
  1815. :help-echo "Change the state."
  1816. :format (if hidden "%t" "%[%t%]")
  1817. :tag (if (memq form '(lisp mismatch))
  1818. (concat "(" magic ")")
  1819. (concat "[" magic "]")))
  1820. children)
  1821. (insert " "))
  1822. (widget-put widget :children children))))
  1823. (defun custom-magic-reset (widget)
  1824. "Redraw the :custom-magic property of WIDGET."
  1825. (let ((magic (widget-get widget :custom-magic)))
  1826. (when magic
  1827. (widget-value-set magic (widget-value magic)))))
  1828. ;;; The `custom' Widget.
  1829. (defface custom-button
  1830. '((((type x w32 ns) (class color)) ; Like default mode line
  1831. :box (:line-width 2 :style released-button)
  1832. :background "lightgrey" :foreground "black"))
  1833. "Face for custom buffer buttons if `custom-raised-buttons' is non-nil."
  1834. :version "21.1"
  1835. :group 'custom-faces)
  1836. (defface custom-button-mouse
  1837. '((((type x w32 ns) (class color))
  1838. :box (:line-width 2 :style released-button)
  1839. :background "grey90" :foreground "black")
  1840. (t
  1841. ;; This is for text terminals that support mouse, like GPM mouse
  1842. ;; or the MS-DOS terminal: inverse-video makes the button stand
  1843. ;; out on mouse-over.
  1844. :inverse-video t))
  1845. "Mouse face for custom buffer buttons if `custom-raised-buttons' is non-nil."
  1846. :version "22.1"
  1847. :group 'custom-faces)
  1848. (defface custom-button-unraised
  1849. '((t :inherit underline))
  1850. "Face for custom buffer buttons if `custom-raised-buttons' is nil."
  1851. :version "22.1"
  1852. :group 'custom-faces)
  1853. (setq custom-button
  1854. (if custom-raised-buttons 'custom-button 'custom-button-unraised))
  1855. (setq custom-button-mouse
  1856. (if custom-raised-buttons 'custom-button-mouse 'highlight))
  1857. (defface custom-button-pressed
  1858. '((((type x w32 ns) (class color))
  1859. :box (:line-width 2 :style pressed-button)
  1860. :background "lightgrey" :foreground "black")
  1861. (t :inverse-video t))
  1862. "Face for pressed custom buttons if `custom-raised-buttons' is non-nil."
  1863. :version "21.1"
  1864. :group 'custom-faces)
  1865. (defface custom-button-pressed-unraised
  1866. '((default :inherit custom-button-unraised)
  1867. (((class color) (background light)) :foreground "magenta4")
  1868. (((class color) (background dark)) :foreground "violet"))
  1869. "Face for pressed custom buttons if `custom-raised-buttons' is nil."
  1870. :version "22.1"
  1871. :group 'custom-faces)
  1872. (setq custom-button-pressed
  1873. (if custom-raised-buttons
  1874. 'custom-button-pressed
  1875. 'custom-button-pressed-unraised))
  1876. (defface custom-documentation '((t nil))
  1877. "Face used for documentation strings in customization buffers."
  1878. :group 'custom-faces)
  1879. (defface custom-state '((((class color) (background dark))
  1880. :foreground "lime green")
  1881. (((class color) (background light))
  1882. :foreground "dark green"))
  1883. "Face used for State descriptions in the customize buffer."
  1884. :group 'custom-faces)
  1885. (defface custom-link '((t :inherit link))
  1886. "Face for links in customization buffers."
  1887. :version "22.1"
  1888. :group 'custom-faces)
  1889. (define-widget 'custom 'default
  1890. "Customize a user option."
  1891. :format "%v"
  1892. :convert-widget 'custom-convert-widget
  1893. :notify 'custom-notify
  1894. :custom-prefix ""
  1895. :custom-level 1
  1896. :custom-state 'hidden
  1897. :documentation-property 'widget-subclass-responsibility
  1898. :value-create 'widget-subclass-responsibility
  1899. :value-delete 'widget-children-value-delete
  1900. :value-get 'widget-value-value-get
  1901. :validate 'widget-children-validate
  1902. :match (lambda (_widget value) (symbolp value)))
  1903. (defun custom-convert-widget (widget)
  1904. "Initialize :value and :tag from :args in WIDGET."
  1905. (let ((args (widget-get widget :args)))
  1906. (when args
  1907. (widget-put widget :value (widget-apply widget
  1908. :value-to-internal (car args)))
  1909. (widget-put widget :tag (custom-unlispify-tag-name (car args)))
  1910. (widget-put widget :args nil)))
  1911. widget)
  1912. (defun custom-notify (widget &rest args)
  1913. "Keep track of changes."
  1914. (let ((state (widget-get widget :custom-state)))
  1915. (unless (eq state 'modified)
  1916. (unless (memq state '(nil unknown hidden))
  1917. (widget-put widget :custom-state 'modified))
  1918. (custom-magic-reset widget)
  1919. (apply 'widget-default-notify widget args))))
  1920. (defun custom-redraw (widget)
  1921. "Redraw WIDGET with current settings."
  1922. (let ((line (count-lines (point-min) (point)))
  1923. (column (current-column))
  1924. (pos (point))
  1925. (from (marker-position (widget-get widget :from)))
  1926. (to (marker-position (widget-get widget :to))))
  1927. (save-excursion
  1928. (widget-value-set widget (widget-value widget))
  1929. (custom-redraw-magic widget))
  1930. (when (and (>= pos from) (<= pos to))
  1931. (condition-case nil
  1932. (progn
  1933. (goto-char (point-min))
  1934. (forward-line (if (> column 0)
  1935. (1- line)
  1936. line))
  1937. (move-to-column column))
  1938. (error nil)))))
  1939. (defun custom-redraw-magic (widget)
  1940. "Redraw WIDGET state with current settings."
  1941. (while widget
  1942. (let ((magic (widget-get widget :custom-magic)))
  1943. (cond (magic
  1944. (widget-value-set magic (widget-value magic))
  1945. (when (setq widget (widget-get widget :group))
  1946. (custom-group-state-update widget)))
  1947. (t
  1948. (setq widget nil)))))
  1949. (widget-setup))
  1950. (defun custom-show (widget value)
  1951. "Non-nil if WIDGET should be shown with VALUE by default."
  1952. (declare (obsolete "this widget type is no longer supported." "24.1"))
  1953. (let ((show (widget-get widget :custom-show)))
  1954. (if (functionp show)
  1955. (funcall show widget value)
  1956. show)))
  1957. (defun custom-load-widget (widget)
  1958. "Load all dependencies for WIDGET."
  1959. (custom-load-symbol (widget-value widget)))
  1960. (defun custom-unloaded-symbol-p (symbol)
  1961. "Return non-nil if the dependencies of SYMBOL have not yet been loaded."
  1962. (let ((found nil)
  1963. (loads (get symbol 'custom-loads))
  1964. load)
  1965. (while loads
  1966. (setq load (car loads)
  1967. loads (cdr loads))
  1968. (cond ((symbolp load)
  1969. (unless (featurep load)
  1970. (setq found t)))
  1971. ((assoc load load-history))
  1972. ((assoc (locate-library load) load-history)
  1973. (message nil))
  1974. (t
  1975. (setq found t))))
  1976. found))
  1977. (defun custom-unloaded-widget-p (widget)
  1978. "Return non-nil if the dependencies of WIDGET have not yet been loaded."
  1979. (custom-unloaded-symbol-p (widget-value widget)))
  1980. (defun custom-toggle-hide (widget)
  1981. "Toggle visibility of WIDGET."
  1982. (custom-load-widget widget)
  1983. (let ((state (widget-get widget :custom-state)))
  1984. (cond ((memq state '(invalid modified set))
  1985. (error "There are unsaved changes"))
  1986. ((eq state 'hidden)
  1987. (widget-put widget :custom-state 'unknown))
  1988. (t
  1989. (widget-put widget :documentation-shown nil)
  1990. (widget-put widget :custom-state 'hidden)))
  1991. (custom-redraw widget)
  1992. (widget-setup)))
  1993. (defun custom-toggle-parent (widget &rest _ignore)
  1994. "Toggle visibility of parent of WIDGET."
  1995. (custom-toggle-hide (widget-get widget :parent)))
  1996. (defun custom-add-see-also (widget &optional prefix)
  1997. "Add `See also ...' to WIDGET if there are any links.
  1998. Insert PREFIX first if non-nil."
  1999. (let* ((symbol (widget-get widget :value))
  2000. (links (get symbol 'custom-links))
  2001. (many (> (length links) 2))
  2002. (buttons (widget-get widget :buttons))
  2003. (indent (widget-get widget :indent)))
  2004. (when links
  2005. (when indent
  2006. (insert-char ?\s indent))
  2007. (when prefix
  2008. (insert prefix))
  2009. (insert "See also ")
  2010. (while links
  2011. (push (widget-create-child-and-convert
  2012. widget (car links)
  2013. :button-face 'custom-link
  2014. :mouse-face 'highlight
  2015. :pressed-face 'highlight)
  2016. buttons)
  2017. (setq links (cdr links))
  2018. (cond ((null links)
  2019. (insert ".\n"))
  2020. ((null (cdr links))
  2021. (if many
  2022. (insert ", and ")
  2023. (insert " and ")))
  2024. (t
  2025. (insert ", "))))
  2026. (widget-put widget :buttons buttons))))
  2027. (defun custom-add-parent-links (widget &optional initial-string _doc-initial-string)
  2028. "Add \"Parent groups: ...\" to WIDGET if the group has parents.
  2029. The value is non-nil if any parents were found.
  2030. If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"."
  2031. (let ((name (widget-value widget))
  2032. (type (widget-type widget))
  2033. (buttons (widget-get widget :buttons))
  2034. (start (point))
  2035. (parents nil))
  2036. (insert (or initial-string "Groups:"))
  2037. (mapatoms (lambda (symbol)
  2038. (when (member (list name type) (get symbol 'custom-group))
  2039. (insert " ")
  2040. (push (widget-create-child-and-convert
  2041. widget 'custom-group-link
  2042. :tag (custom-unlispify-tag-name symbol)
  2043. symbol)
  2044. buttons)
  2045. (setq parents (cons symbol parents)))))
  2046. (if parents
  2047. (insert "\n")
  2048. (delete-region start (point)))
  2049. (widget-put widget :buttons buttons)
  2050. parents))
  2051. ;;; The `custom-comment' Widget.
  2052. ;; like the editable field
  2053. (defface custom-comment '((((type tty))
  2054. :background "yellow3"
  2055. :foreground "black")
  2056. (((class grayscale color)
  2057. (background light))
  2058. :background "gray85")
  2059. (((class grayscale color)
  2060. (background dark))
  2061. :background "dim gray")
  2062. (t
  2063. :slant italic))
  2064. "Face used for comments on variables or faces."
  2065. :version "21.1"
  2066. :group 'custom-faces)
  2067. ;; like font-lock-comment-face
  2068. (defface custom-comment-tag
  2069. '((((class color) (background dark)) :foreground "gray80")
  2070. (((class color) (background light)) :foreground "blue4")
  2071. (((class grayscale) (background light))
  2072. :foreground "DimGray" :weight bold :slant italic)
  2073. (((class grayscale) (background dark))
  2074. :foreground "LightGray" :weight bold :slant italic)
  2075. (t :weight bold))
  2076. "Face used for the comment tag on variables or faces."
  2077. :group 'custom-faces)
  2078. (define-widget 'custom-comment 'string
  2079. "User comment."
  2080. :tag "Comment"
  2081. :help-echo "Edit a comment here."
  2082. :sample-face 'custom-comment-tag
  2083. :value-face 'custom-comment
  2084. :shown nil
  2085. :create 'custom-comment-create)
  2086. (defun custom-comment-create (widget)
  2087. (let* ((null-comment (equal "" (widget-value widget))))
  2088. (if (or (widget-get (widget-get widget :parent) :comment-shown)
  2089. (not null-comment))
  2090. (widget-default-create widget)
  2091. ;; `widget-default-delete' expects markers in these slots --
  2092. ;; maybe it shouldn't.
  2093. (widget-put widget :from (point-marker))
  2094. (widget-put widget :to (point-marker)))))
  2095. (defun custom-comment-hide (widget)
  2096. (widget-put (widget-get widget :parent) :comment-shown nil))
  2097. ;; Those functions are for the menu. WIDGET is NOT the comment widget. It's
  2098. ;; the global custom one
  2099. (defun custom-comment-show (widget)
  2100. (widget-put widget :comment-shown t)
  2101. (custom-redraw widget)
  2102. (widget-setup))
  2103. (defun custom-comment-invisible-p (widget)
  2104. (let ((val (widget-value (widget-get widget :comment-widget))))
  2105. (and (equal "" val)
  2106. (not (widget-get widget :comment-shown)))))
  2107. ;;; The `custom-variable' Widget.
  2108. (defface custom-variable-tag
  2109. `((((class color) (background dark))
  2110. :foreground "light blue" :weight bold)
  2111. (((min-colors 88) (class color) (background light))
  2112. :foreground "blue1" :weight bold)
  2113. (((class color) (background light))
  2114. :foreground "blue" :weight bold)
  2115. (t :weight bold))
  2116. "Face used for unpushable variable tags."
  2117. :group 'custom-faces)
  2118. (defface custom-variable-button '((t :underline t :weight bold))
  2119. "Face used for pushable variable tags."
  2120. :group 'custom-faces)
  2121. (defcustom custom-variable-default-form 'edit
  2122. "Default form of displaying variable values."
  2123. :type '(choice (const edit)
  2124. (const lisp))
  2125. :group 'custom-buffer
  2126. :version "20.3")
  2127. (defun custom-variable-documentation (variable)
  2128. "Return documentation of VARIABLE for use in Custom buffer.
  2129. Normally just return the docstring. But if VARIABLE automatically
  2130. becomes buffer local when set, append a message to that effect."
  2131. (format "%s%s" (documentation-property variable 'variable-documentation t)
  2132. (if (and (local-variable-if-set-p variable)
  2133. (or (not (local-variable-p variable))
  2134. (with-temp-buffer
  2135. (local-variable-if-set-p variable))))
  2136. "\n
  2137. This variable automatically becomes buffer-local when set outside Custom.
  2138. However, setting it through Custom sets the default value."
  2139. "")))
  2140. (define-widget 'custom-variable 'custom
  2141. "A widget for displaying a Custom variable.
  2142. The following properties have special meanings for this widget:
  2143. :hidden-states should be a list of widget states for which the
  2144. widget's initial contents are to be hidden.
  2145. :custom-form should be a symbol describing how to display and
  2146. edit the variable---either `edit' (using edit widgets),
  2147. `lisp' (as a Lisp sexp), or `mismatch' (should not happen);
  2148. if nil, use the return value of `custom-variable-default-form'.
  2149. :shown-value, if non-nil, should be a list whose `car' is the
  2150. variable value to display in place of the current value.
  2151. :custom-style describes the widget interface style; nil is the
  2152. default style, while `simple' means a simpler interface that
  2153. inhibits the magic custom-state widget."
  2154. :format "%v"
  2155. :help-echo "Set or reset this variable."
  2156. :documentation-property #'custom-variable-documentation
  2157. :custom-category 'option
  2158. :custom-state nil
  2159. :custom-menu 'custom-variable-menu-create
  2160. :custom-form nil
  2161. :value-create 'custom-variable-value-create
  2162. :action 'custom-variable-action
  2163. :hidden-states '(standard)
  2164. :custom-set 'custom-variable-set
  2165. :custom-mark-to-save 'custom-variable-mark-to-save
  2166. :custom-reset-current 'custom-redraw
  2167. :custom-reset-saved 'custom-variable-reset-saved
  2168. :custom-reset-standard 'custom-variable-reset-standard
  2169. :custom-mark-to-reset-standard 'custom-variable-mark-to-reset-standard
  2170. :custom-standard-value 'custom-variable-standard-value
  2171. :custom-state-set-and-redraw 'custom-variable-state-set-and-redraw)
  2172. (defun custom-variable-type (symbol)
  2173. "Return a widget suitable for editing the value of SYMBOL.
  2174. If SYMBOL has a `custom-type' property, use that.
  2175. Otherwise, try matching SYMBOL against `custom-guess-name-alist' and
  2176. try matching its doc string against `custom-guess-doc-alist'."
  2177. (let* ((type (or (get symbol 'custom-type)
  2178. (and (not (get symbol 'standard-value))
  2179. (custom-guess-type symbol))
  2180. 'sexp))
  2181. (options (get symbol 'custom-options))
  2182. (tmp (if (listp type)
  2183. (copy-sequence type)
  2184. (list type))))
  2185. (when options
  2186. (widget-put tmp :options options))
  2187. tmp))
  2188. (defun custom-variable-value-create (widget)
  2189. "Here is where you edit the variable's value."
  2190. (custom-load-widget widget)
  2191. (unless (widget-get widget :custom-form)
  2192. (widget-put widget :custom-form custom-variable-default-form))
  2193. (let* ((buttons (widget-get widget :buttons))
  2194. (children (widget-get widget :children))
  2195. (form (widget-get widget :custom-form))
  2196. (symbol (widget-get widget :value))
  2197. (tag (widget-get widget :tag))
  2198. (type (custom-variable-type symbol))
  2199. (conv (widget-convert type))
  2200. (get (or (get symbol 'custom-get) 'default-value))
  2201. (prefix (widget-get widget :custom-prefix))
  2202. (last (widget-get widget :custom-last))
  2203. (style (widget-get widget :custom-style))
  2204. (value (let ((shown-value (widget-get widget :shown-value)))
  2205. (cond (shown-value
  2206. (car shown-value))
  2207. ((default-boundp symbol)
  2208. (funcall get symbol))
  2209. (t (widget-get conv :value)))))
  2210. (state (or (widget-get widget :custom-state)
  2211. (if (memq (custom-variable-state symbol value)
  2212. (widget-get widget :hidden-states))
  2213. 'hidden))))
  2214. ;; If we don't know the state, see if we need to edit it in lisp form.
  2215. (unless state
  2216. (setq state (if (custom-show type value) 'unknown 'hidden)))
  2217. (when (eq state 'unknown)
  2218. (unless (widget-apply conv :match value)
  2219. (setq form 'mismatch)))
  2220. ;; Now we can create the child widget.
  2221. (cond ((eq custom-buffer-style 'tree)
  2222. (insert prefix (if last " `--- " " |--- "))
  2223. (push (widget-create-child-and-convert
  2224. widget 'custom-browse-variable-tag)
  2225. buttons)
  2226. (insert " " tag "\n")
  2227. (widget-put widget :buttons buttons))
  2228. ((eq state 'hidden)
  2229. ;; Indicate hidden value.
  2230. (push (widget-create-child-and-convert
  2231. widget 'custom-visibility
  2232. :help-echo "Show the value of this option."
  2233. :on-glyph "down"
  2234. :on "Hide"
  2235. :off-glyph "right"
  2236. :off "Show Value"
  2237. :action 'custom-toggle-hide-variable
  2238. nil)
  2239. buttons)
  2240. (insert " ")
  2241. (push (widget-create-child-and-convert
  2242. widget 'item
  2243. :format "%{%t%} "
  2244. :sample-face 'custom-variable-tag
  2245. :tag tag
  2246. :parent widget)
  2247. buttons))
  2248. ((memq form '(lisp mismatch))
  2249. (push (widget-create-child-and-convert
  2250. widget 'custom-visibility
  2251. :help-echo "Hide the value of this option."
  2252. :on "Hide"
  2253. :off "Show"
  2254. :on-glyph "down"
  2255. :off-glyph "right"
  2256. :action 'custom-toggle-hide-variable
  2257. t)
  2258. buttons)
  2259. (insert " ")
  2260. ;; This used to try presenting the saved value or the
  2261. ;; standard value, but it seems more intuitive to present
  2262. ;; the current value (Bug#7600).
  2263. (let* ((value (cond ((default-boundp symbol)
  2264. (custom-quote (funcall get symbol)))
  2265. (t
  2266. (custom-quote (widget-get conv :value))))))
  2267. (insert (symbol-name symbol) ": ")
  2268. (push (widget-create-child-and-convert
  2269. widget 'sexp
  2270. :button-face 'custom-variable-button-face
  2271. :format "%v"
  2272. :tag (symbol-name symbol)
  2273. :parent widget
  2274. :value value)
  2275. children)))
  2276. (t
  2277. ;; Edit mode.
  2278. (push (widget-create-child-and-convert
  2279. widget 'custom-visibility
  2280. :help-echo "Hide or show this option."
  2281. :on "Hide"
  2282. :off "Show"
  2283. :on-glyph "down"
  2284. :off-glyph "right"
  2285. :action 'custom-toggle-hide-variable
  2286. t)
  2287. buttons)
  2288. (insert " ")
  2289. (let* ((format (widget-get type :format))
  2290. tag-format value-format)
  2291. (unless (string-match ":" format)
  2292. (error "Bad format"))
  2293. (setq tag-format (substring format 0 (match-end 0)))
  2294. (setq value-format (substring format (match-end 0)))
  2295. (push (widget-create-child-and-convert
  2296. widget 'item
  2297. :format tag-format
  2298. :action 'custom-tag-action
  2299. :help-echo "Change value of this option."
  2300. :mouse-down-action 'custom-tag-mouse-down-action
  2301. :button-face 'custom-variable-button
  2302. :sample-face 'custom-variable-tag
  2303. tag)
  2304. buttons)
  2305. (push (widget-create-child-and-convert
  2306. widget type
  2307. :format value-format
  2308. :value value)
  2309. children))))
  2310. (unless (eq custom-buffer-style 'tree)
  2311. (unless (eq (preceding-char) ?\n)
  2312. (widget-insert "\n"))
  2313. ;; Create the magic button.
  2314. (unless (eq style 'simple)
  2315. (let ((magic (widget-create-child-and-convert
  2316. widget 'custom-magic nil)))
  2317. (widget-put widget :custom-magic magic)
  2318. (push magic buttons)))
  2319. (widget-put widget :buttons buttons)
  2320. ;; Insert documentation.
  2321. (widget-put widget :documentation-indent 3)
  2322. (unless (and (eq style 'simple)
  2323. (eq state 'hidden))
  2324. (widget-add-documentation-string-button
  2325. widget :visibility-widget 'custom-visibility))
  2326. ;; The comment field
  2327. (unless (eq state 'hidden)
  2328. (let* ((comment (get symbol 'variable-comment))
  2329. (comment-widget
  2330. (widget-create-child-and-convert
  2331. widget 'custom-comment
  2332. :parent widget
  2333. :value (or comment ""))))
  2334. (widget-put widget :comment-widget comment-widget)
  2335. ;; Don't push it !!! Custom assumes that the first child is the
  2336. ;; value one.
  2337. (setq children (append children (list comment-widget)))))
  2338. ;; Update the rest of the properties.
  2339. (widget-put widget :custom-form form)
  2340. (widget-put widget :children children)
  2341. ;; Now update the state.
  2342. (if (eq state 'hidden)
  2343. (widget-put widget :custom-state state)
  2344. (custom-variable-state-set widget))
  2345. ;; See also.
  2346. (unless (eq state 'hidden)
  2347. (when (eq (widget-get widget :custom-level) 1)
  2348. (custom-add-parent-links widget))
  2349. (custom-add-see-also widget)))))
  2350. (defun custom-toggle-hide-variable (visibility-widget &rest _ignore)
  2351. "Toggle the visibility of a `custom-variable' parent widget.
  2352. By default, this signals an error if the parent has unsaved
  2353. changes. If the parent has a `simple' :custom-style property,
  2354. the present value is saved to its :shown-value property instead."
  2355. (let ((widget (widget-get visibility-widget :parent)))
  2356. (unless (eq (widget-type widget) 'custom-variable)
  2357. (error "Invalid widget type"))
  2358. (custom-load-widget widget)
  2359. (let ((state (widget-get widget :custom-state)))
  2360. (if (eq state 'hidden)
  2361. (widget-put widget :custom-state 'unknown)
  2362. ;; In normal interface, widget can't be hidden if modified.
  2363. (when (memq state '(invalid modified set))
  2364. (if (eq (widget-get widget :custom-style) 'simple)
  2365. (widget-put widget :shown-value
  2366. (list (widget-value
  2367. (car-safe
  2368. (widget-get widget :children)))))
  2369. (error "There are unsaved changes")))
  2370. (widget-put widget :documentation-shown nil)
  2371. (widget-put widget :custom-state 'hidden))
  2372. (custom-redraw widget)
  2373. (widget-setup))))
  2374. (defun custom-tag-action (widget &rest args)
  2375. "Pass :action to first child of WIDGET's parent."
  2376. (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children))
  2377. :action args))
  2378. (defun custom-tag-mouse-down-action (widget &rest args)
  2379. "Pass :mouse-down-action to first child of WIDGET's parent."
  2380. (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children))
  2381. :mouse-down-action args))
  2382. (defun custom-variable-state (symbol val)
  2383. "Return the state of SYMBOL if its value is VAL.
  2384. If SYMBOL has a non-nil `custom-get' property, it overrides VAL.
  2385. Possible return values are `standard', `saved', `set', `themed',
  2386. `changed', and `rogue'."
  2387. (let* ((get (or (get symbol 'custom-get) 'default-value))
  2388. (value (if (default-boundp symbol)
  2389. (funcall get symbol)
  2390. val))
  2391. (comment (get symbol 'variable-comment))
  2392. tmp
  2393. temp)
  2394. (cond ((progn (setq tmp (get symbol 'customized-value))
  2395. (setq temp
  2396. (get symbol 'customized-variable-comment))
  2397. (or tmp temp))
  2398. (if (condition-case nil
  2399. (and (equal value (eval (car tmp)))
  2400. (equal comment temp))
  2401. (error nil))
  2402. 'set
  2403. 'changed))
  2404. ((progn (setq tmp (get symbol 'theme-value))
  2405. (setq temp (get symbol 'saved-variable-comment))
  2406. (or tmp temp))
  2407. (if (condition-case nil
  2408. (and (equal comment temp)
  2409. (equal value
  2410. (eval
  2411. (car (custom-variable-theme-value
  2412. symbol)))))
  2413. (error nil))
  2414. (cond
  2415. ((eq (caar tmp) 'user) 'saved)
  2416. ((eq (caar tmp) 'changed)
  2417. (if (condition-case nil
  2418. (and (null comment)
  2419. (equal value
  2420. (eval
  2421. (car (get symbol 'standard-value)))))
  2422. (error nil))
  2423. ;; The value was originally set outside
  2424. ;; custom, but it was set to the standard
  2425. ;; value (probably an autoloaded defcustom).
  2426. 'standard
  2427. 'changed))
  2428. (t 'themed))
  2429. 'changed))
  2430. ((setq tmp (get symbol 'standard-value))
  2431. (if (condition-case nil
  2432. (and (equal value (eval (car tmp)))
  2433. (equal comment nil))
  2434. (error nil))
  2435. 'standard
  2436. 'changed))
  2437. (t 'rogue))))
  2438. (defun custom-variable-state-set (widget &optional state)
  2439. "Set the state of WIDGET to STATE.
  2440. If STATE is nil, the value is computed by `custom-variable-state'."
  2441. (widget-put widget :custom-state
  2442. (or state (custom-variable-state (widget-value widget)
  2443. (widget-get widget :value)))))
  2444. (defun custom-variable-standard-value (widget)
  2445. (get (widget-value widget) 'standard-value))
  2446. (defvar custom-variable-menu
  2447. `(("Set for Current Session" custom-variable-set
  2448. (lambda (widget)
  2449. (eq (widget-get widget :custom-state) 'modified)))
  2450. ;; Note that in all the backquoted code in this file, we test
  2451. ;; init-file-user rather than user-init-file. This is in case
  2452. ;; cus-edit is loaded by something in site-start.el, because
  2453. ;; user-init-file is not set at that stage.
  2454. ;; http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg00310.html
  2455. ,@(when (or custom-file init-file-user)
  2456. '(("Save for Future Sessions" custom-variable-save
  2457. (lambda (widget)
  2458. (memq (widget-get widget :custom-state)
  2459. '(modified set changed rogue))))))
  2460. ("Undo Edits" custom-redraw
  2461. (lambda (widget)
  2462. (and (default-boundp (widget-value widget))
  2463. (memq (widget-get widget :custom-state) '(modified changed)))))
  2464. ("Revert This Session's Customization" custom-variable-reset-saved
  2465. (lambda (widget)
  2466. (memq (widget-get widget :custom-state)
  2467. '(modified set changed rogue))))
  2468. ,@(when (or custom-file init-file-user)
  2469. '(("Erase Customization" custom-variable-reset-standard
  2470. (lambda (widget)
  2471. (and (get (widget-value widget) 'standard-value)
  2472. (memq (widget-get widget :custom-state)
  2473. '(modified set changed saved rogue)))))))
  2474. ("Set to Backup Value" custom-variable-reset-backup
  2475. (lambda (widget)
  2476. (get (widget-value widget) 'backup-value)))
  2477. ("---" ignore ignore)
  2478. ("Add Comment" custom-comment-show custom-comment-invisible-p)
  2479. ("---" ignore ignore)
  2480. ("Show Current Value" custom-variable-edit
  2481. (lambda (widget)
  2482. (eq (widget-get widget :custom-form) 'lisp)))
  2483. ("Show Saved Lisp Expression" custom-variable-edit-lisp
  2484. (lambda (widget)
  2485. (eq (widget-get widget :custom-form) 'edit))))
  2486. "Alist of actions for the `custom-variable' widget.
  2487. Each entry has the form (NAME ACTION FILTER) where NAME is the name of
  2488. the menu entry, ACTION is the function to call on the widget when the
  2489. menu is selected, and FILTER is a predicate which takes a `custom-variable'
  2490. widget as an argument, and returns non-nil if ACTION is valid on that
  2491. widget. If FILTER is nil, ACTION is always valid.")
  2492. (defun custom-variable-action (widget &optional event)
  2493. "Show the menu for `custom-variable' WIDGET.
  2494. Optional EVENT is the location for the menu."
  2495. (if (eq (widget-get widget :custom-state) 'hidden)
  2496. (custom-toggle-hide widget)
  2497. (unless (eq (widget-get widget :custom-state) 'modified)
  2498. (custom-variable-state-set widget))
  2499. (custom-redraw-magic widget)
  2500. (let* ((completion-ignore-case t)
  2501. (answer (widget-choose (concat "Operation on "
  2502. (custom-unlispify-tag-name
  2503. (widget-get widget :value)))
  2504. (custom-menu-filter custom-variable-menu
  2505. widget)
  2506. event)))
  2507. (if answer
  2508. (funcall answer widget)))))
  2509. (defun custom-variable-edit (widget)
  2510. "Edit value of WIDGET."
  2511. (widget-put widget :custom-state 'unknown)
  2512. (widget-put widget :custom-form 'edit)
  2513. (custom-redraw widget))
  2514. (defun custom-variable-edit-lisp (widget)
  2515. "Edit the Lisp representation of the value of WIDGET."
  2516. (widget-put widget :custom-state 'unknown)
  2517. (widget-put widget :custom-form 'lisp)
  2518. (custom-redraw widget))
  2519. (defun custom-variable-set (widget)
  2520. "Set the current value for the variable being edited by WIDGET."
  2521. (let* ((form (widget-get widget :custom-form))
  2522. (state (widget-get widget :custom-state))
  2523. (child (car (widget-get widget :children)))
  2524. (symbol (widget-value widget))
  2525. (set (or (get symbol 'custom-set) 'set-default))
  2526. (comment-widget (widget-get widget :comment-widget))
  2527. (comment (widget-value comment-widget))
  2528. val)
  2529. (cond ((eq state 'hidden)
  2530. (user-error "Cannot set hidden variable"))
  2531. ((setq val (widget-apply child :validate))
  2532. (goto-char (widget-get val :from))
  2533. (error "%s" (widget-get val :error)))
  2534. ((memq form '(lisp mismatch))
  2535. (when (equal comment "")
  2536. (setq comment nil)
  2537. ;; Make the comment invisible by hand if it's empty
  2538. (custom-comment-hide comment-widget))
  2539. (custom-variable-backup-value widget)
  2540. (custom-push-theme 'theme-value symbol 'user
  2541. 'set (custom-quote (widget-value child)))
  2542. (funcall set symbol (eval (setq val (widget-value child))))
  2543. (put symbol 'customized-value (list val))
  2544. (put symbol 'variable-comment comment)
  2545. (put symbol 'customized-variable-comment comment))
  2546. (t
  2547. (when (equal comment "")
  2548. (setq comment nil)
  2549. ;; Make the comment invisible by hand if it's empty
  2550. (custom-comment-hide comment-widget))
  2551. (custom-variable-backup-value widget)
  2552. (custom-push-theme 'theme-value symbol 'user
  2553. 'set (custom-quote (widget-value child)))
  2554. (funcall set symbol (setq val (widget-value child)))
  2555. (put symbol 'customized-value (list (custom-quote val)))
  2556. (put symbol 'variable-comment comment)
  2557. (put symbol 'customized-variable-comment comment)))
  2558. (custom-variable-state-set widget)
  2559. (custom-redraw-magic widget)))
  2560. (defun custom-variable-mark-to-save (widget)
  2561. "Set value and mark for saving the variable edited by WIDGET."
  2562. (let* ((form (widget-get widget :custom-form))
  2563. (state (widget-get widget :custom-state))
  2564. (child (car (widget-get widget :children)))
  2565. (symbol (widget-value widget))
  2566. (set (or (get symbol 'custom-set) 'set-default))
  2567. (comment-widget (widget-get widget :comment-widget))
  2568. (comment (widget-value comment-widget))
  2569. val)
  2570. (cond ((eq state 'hidden)
  2571. (user-error "Cannot set hidden variable"))
  2572. ((setq val (widget-apply child :validate))
  2573. (goto-char (widget-get val :from))
  2574. (error "Saving %s: %s" symbol (widget-get val :error)))
  2575. ((memq form '(lisp mismatch))
  2576. (when (equal comment "")
  2577. (setq comment nil)
  2578. ;; Make the comment invisible by hand if it's empty
  2579. (custom-comment-hide comment-widget))
  2580. (put symbol 'saved-value (list (widget-value child)))
  2581. (custom-push-theme 'theme-value symbol 'user
  2582. 'set (custom-quote (widget-value child)))
  2583. (funcall set symbol (eval (widget-value child)))
  2584. (put symbol 'variable-comment comment)
  2585. (put symbol 'saved-variable-comment comment))
  2586. (t
  2587. (when (equal comment "")
  2588. (setq comment nil)
  2589. ;; Make the comment invisible by hand if it's empty
  2590. (custom-comment-hide comment-widget))
  2591. (put symbol 'saved-value
  2592. (list (custom-quote (widget-value child))))
  2593. (custom-push-theme 'theme-value symbol 'user
  2594. 'set (custom-quote (widget-value child)))
  2595. (funcall set symbol (widget-value child))
  2596. (put symbol 'variable-comment comment)
  2597. (put symbol 'saved-variable-comment comment)))
  2598. (put symbol 'customized-value nil)
  2599. (put symbol 'customized-variable-comment nil)))
  2600. (defsubst custom-variable-state-set-and-redraw (widget)
  2601. "Set state of variable widget WIDGET and redraw with current settings."
  2602. (custom-variable-state-set widget)
  2603. (custom-redraw-magic widget))
  2604. (defun custom-variable-save (widget)
  2605. "Save value of variable edited by widget WIDGET."
  2606. (custom-variable-mark-to-save widget)
  2607. (custom-save-all)
  2608. (custom-variable-state-set-and-redraw widget))
  2609. (defun custom-variable-reset-saved (widget)
  2610. "Restore the value of the variable being edited by WIDGET.
  2611. If there is a saved value, restore it; otherwise reset to the
  2612. uncustomized (themed or standard) value.
  2613. Update the widget to show that value. The value that was current
  2614. before this operation becomes the backup value."
  2615. (let* ((symbol (widget-value widget))
  2616. (saved-value (get symbol 'saved-value))
  2617. (comment (get symbol 'saved-variable-comment)))
  2618. (custom-variable-backup-value widget)
  2619. (if (not (or saved-value comment))
  2620. ;; If there is no saved value, remove the setting.
  2621. (custom-push-theme 'theme-value symbol 'user 'reset)
  2622. ;; Otherwise, apply the saved value.
  2623. (put symbol 'variable-comment comment)
  2624. (custom-push-theme 'theme-value symbol 'user 'set (car-safe saved-value))
  2625. (ignore-errors
  2626. (funcall (or (get symbol 'custom-set) 'set-default)
  2627. symbol (eval (car saved-value)))))
  2628. (put symbol 'customized-value nil)
  2629. (put symbol 'customized-variable-comment nil)
  2630. (widget-put widget :custom-state 'unknown)
  2631. ;; This call will possibly make the comment invisible
  2632. (custom-redraw widget)))
  2633. (defun custom-variable-mark-to-reset-standard (widget)
  2634. "Mark to restore standard setting for the variable edited by widget WIDGET.
  2635. If `custom-reset-standard-variables-list' is nil, save, reset and
  2636. redraw the widget immediately."
  2637. (let* ((symbol (widget-value widget)))
  2638. (if (get symbol 'standard-value)
  2639. (custom-variable-backup-value widget)
  2640. (user-error "No standard setting known for %S" symbol))
  2641. (put symbol 'variable-comment nil)
  2642. (put symbol 'customized-value nil)
  2643. (put symbol 'customized-variable-comment nil)
  2644. (custom-push-theme 'theme-value symbol 'user 'reset)
  2645. (custom-theme-recalc-variable symbol)
  2646. (if (and custom-reset-standard-variables-list
  2647. (or (get symbol 'saved-value) (get symbol 'saved-variable-comment)))
  2648. (progn
  2649. (put symbol 'saved-value nil)
  2650. (put symbol 'saved-variable-comment nil)
  2651. ;; Append this to `custom-reset-standard-variables-list' to
  2652. ;; have `custom-reset-standard-save-and-update' save setting
  2653. ;; to the file, update the widget's state, and redraw it.
  2654. (setq custom-reset-standard-variables-list
  2655. (cons widget custom-reset-standard-variables-list)))
  2656. (when (or (get symbol 'saved-value) (get symbol 'saved-variable-comment))
  2657. (put symbol 'saved-value nil)
  2658. (put symbol 'saved-variable-comment nil)
  2659. (custom-save-all))
  2660. (widget-put widget :custom-state 'unknown)
  2661. ;; This call will possibly make the comment invisible
  2662. (custom-redraw widget))))
  2663. (defun custom-variable-reset-standard (widget)
  2664. "Restore standard setting for the variable edited by WIDGET.
  2665. This operation eliminates any saved setting for the variable,
  2666. restoring it to the state of a variable that has never been customized.
  2667. The value that was current before this operation
  2668. becomes the backup value, so you can get it again."
  2669. (let (custom-reset-standard-variables-list)
  2670. (custom-variable-mark-to-reset-standard widget)))
  2671. (defun custom-variable-backup-value (widget)
  2672. "Back up the current value for WIDGET's variable.
  2673. The backup value is kept in the car of the `backup-value' property."
  2674. (let* ((symbol (widget-value widget))
  2675. (get (or (get symbol 'custom-get) 'default-value))
  2676. (type (custom-variable-type symbol))
  2677. (conv (widget-convert type))
  2678. (value (if (default-boundp symbol)
  2679. (funcall get symbol)
  2680. (widget-get conv :value))))
  2681. (put symbol 'backup-value (list value))))
  2682. (defun custom-variable-reset-backup (widget)
  2683. "Restore the backup value for the variable being edited by WIDGET.
  2684. The value that was current before this operation
  2685. becomes the backup value, so you can use this operation repeatedly
  2686. to switch between two values."
  2687. (let* ((symbol (widget-value widget))
  2688. (set (or (get symbol 'custom-set) 'set-default))
  2689. (value (get symbol 'backup-value))
  2690. (comment-widget (widget-get widget :comment-widget))
  2691. (comment (widget-value comment-widget)))
  2692. (if value
  2693. (progn
  2694. (custom-variable-backup-value widget)
  2695. (custom-push-theme 'theme-value symbol 'user 'set value)
  2696. (condition-case nil
  2697. (funcall set symbol (car value))
  2698. (error nil)))
  2699. (user-error "No backup value for %s" symbol))
  2700. (put symbol 'customized-value (list (custom-quote (car value))))
  2701. (put symbol 'variable-comment comment)
  2702. (put symbol 'customized-variable-comment comment)
  2703. (custom-variable-state-set widget)
  2704. ;; This call will possibly make the comment invisible
  2705. (custom-redraw widget)))
  2706. ;;; The `custom-visibility' Widget
  2707. (define-widget 'custom-visibility 'visibility
  2708. "Show or hide a documentation string."
  2709. :button-face 'custom-visibility
  2710. :pressed-face 'custom-visibility
  2711. :mouse-face 'highlight
  2712. :pressed-face 'highlight
  2713. :on-glyph nil
  2714. :off-glyph nil)
  2715. (defface custom-visibility
  2716. '((t :height 0.8 :inherit link))
  2717. "Face for the `custom-visibility' widget."
  2718. :version "23.1"
  2719. :group 'custom-faces)
  2720. ;;; The `custom-face-edit' Widget.
  2721. (define-widget 'custom-face-edit 'checklist
  2722. "Widget for editing face attributes.
  2723. The following properties have special meanings for this widget:
  2724. :value is a plist of face attributes.
  2725. :default-face-attributes, if non-nil, is a plist of defaults for
  2726. face attributes (as specified by a `default' defface entry)."
  2727. :format "%v"
  2728. :extra-offset 3
  2729. :button-args '(:help-echo "Control whether this attribute has any effect.")
  2730. :value-to-internal 'custom-face-edit-fix-value
  2731. :match (lambda (widget value)
  2732. (widget-checklist-match widget
  2733. (custom-face-edit-fix-value widget value)))
  2734. :value-create 'custom-face-edit-value-create
  2735. :convert-widget 'custom-face-edit-convert-widget
  2736. :args (mapcar (lambda (att)
  2737. (list 'group :inline t
  2738. :sibling-args (widget-get (nth 1 att) :sibling-args)
  2739. (list 'const :format "" :value (nth 0 att))
  2740. (nth 1 att)))
  2741. custom-face-attributes))
  2742. (defun custom-face-edit-value-create (widget)
  2743. (let* ((alist (widget-checklist-match-find
  2744. widget (widget-get widget :value)))
  2745. (args (widget-get widget :args))
  2746. (show-all (widget-get widget :show-all-attributes))
  2747. (buttons (widget-get widget :buttons))
  2748. (defaults (widget-checklist-match-find
  2749. widget
  2750. (widget-get widget :default-face-attributes)))
  2751. entry)
  2752. (unless (looking-back "^ *" (line-beginning-position))
  2753. (insert ?\n))
  2754. (insert-char ?\s (widget-get widget :extra-offset))
  2755. (if (or alist defaults show-all)
  2756. (dolist (prop args)
  2757. (setq entry (or (assq prop alist)
  2758. (assq prop defaults)))
  2759. (if (or entry show-all)
  2760. (widget-checklist-add-item widget prop entry)))
  2761. (insert (propertize "-- Empty face --" 'face 'shadow) ?\n))
  2762. (let ((indent (widget-get widget :indent)))
  2763. (if indent (insert-char ?\s (widget-get widget :indent))))
  2764. (push (widget-create-child-and-convert
  2765. widget 'visibility
  2766. :help-echo "Show or hide all face attributes."
  2767. :button-face 'custom-visibility
  2768. :pressed-face 'custom-visibility
  2769. :mouse-face 'highlight
  2770. :on "Hide Unused Attributes" :off "Show All Attributes"
  2771. :on-glyph nil :off-glyph nil
  2772. :always-active t
  2773. :action 'custom-face-edit-value-visibility-action
  2774. show-all)
  2775. buttons)
  2776. (insert ?\n)
  2777. (widget-put widget :buttons buttons)
  2778. (widget-put widget :children (nreverse (widget-get widget :children)))))
  2779. (defun custom-face-edit-value-visibility-action (widget &rest _ignore)
  2780. ;; Toggle hiding of face attributes.
  2781. (let ((parent (widget-get widget :parent)))
  2782. (widget-put parent :show-all-attributes
  2783. (not (widget-get parent :show-all-attributes)))
  2784. (custom-redraw parent)))
  2785. (defun custom-face-edit-fix-value (_widget value)
  2786. "Ignoring WIDGET, convert :bold and :italic in VALUE to new form.
  2787. Also change :reverse-video to :inverse-video."
  2788. (custom-fix-face-spec value))
  2789. (defun custom-face-edit-convert-widget (widget)
  2790. "Convert :args as widget types in WIDGET."
  2791. (widget-put
  2792. widget
  2793. :args (mapcar (lambda (arg)
  2794. (widget-convert arg
  2795. :deactivate 'custom-face-edit-deactivate
  2796. :activate 'custom-face-edit-activate
  2797. :delete 'custom-face-edit-delete))
  2798. (widget-get widget :args)))
  2799. widget)
  2800. (defconst custom-face-edit (widget-convert 'custom-face-edit)
  2801. "Converted version of the `custom-face-edit' widget.")
  2802. (defun custom-face-edit-deactivate (widget)
  2803. "Make face widget WIDGET inactive for user modifications."
  2804. (unless (widget-get widget :inactive)
  2805. (let ((tag (custom-face-edit-attribute-tag widget))
  2806. (from (copy-marker (widget-get widget :from)))
  2807. (value (widget-value widget))
  2808. (inhibit-read-only t)
  2809. (inhibit-modification-hooks t))
  2810. (save-excursion
  2811. (goto-char from)
  2812. (widget-default-delete widget)
  2813. (insert tag ": " (propertize "--" 'face 'shadow) "\n")
  2814. (widget-put widget :inactive
  2815. (cons value (cons from (- (point) from))))))))
  2816. (defun custom-face-edit-activate (widget)
  2817. "Make face widget WIDGET active for user modifications."
  2818. (let ((inactive (widget-get widget :inactive))
  2819. (inhibit-read-only t)
  2820. (inhibit-modification-hooks t))
  2821. (when (consp inactive)
  2822. (save-excursion
  2823. (goto-char (car (cdr inactive)))
  2824. (delete-region (point) (+ (point) (cdr (cdr inactive))))
  2825. (widget-put widget :inactive nil)
  2826. (widget-apply widget :create)
  2827. (widget-value-set widget (car inactive))
  2828. (widget-setup)))))
  2829. (defun custom-face-edit-delete (widget)
  2830. "Remove WIDGET from the buffer."
  2831. (let ((inactive (widget-get widget :inactive))
  2832. (inhibit-read-only t)
  2833. (inhibit-modification-hooks t))
  2834. (if (not inactive)
  2835. ;; Widget is alive, we don't have to do anything special
  2836. (widget-default-delete widget)
  2837. ;; WIDGET is already deleted because we did so to deactivate it;
  2838. ;; now just get rid of the label we put in its place.
  2839. (delete-region (car (cdr inactive))
  2840. (+ (car (cdr inactive)) (cdr (cdr inactive))))
  2841. (widget-put widget :inactive nil))))
  2842. (defun custom-face-edit-attribute-tag (widget)
  2843. "Return the first :tag property in WIDGET or one of its children."
  2844. (let ((tag (widget-get widget :tag)))
  2845. (or (and (not (equal tag "")) tag)
  2846. (let ((children (widget-get widget :children)))
  2847. (while (and (null tag) children)
  2848. (setq tag (custom-face-edit-attribute-tag (pop children))))
  2849. tag))))
  2850. ;;; The `custom-display' Widget.
  2851. (define-widget 'custom-display 'menu-choice
  2852. "Select a display type."
  2853. :tag "Display"
  2854. :value t
  2855. :help-echo "Specify frames where the face attributes should be used."
  2856. :args '((const :tag "all" t)
  2857. (const :tag "defaults" default)
  2858. (checklist
  2859. :tag "specific display"
  2860. :offset 0
  2861. :extra-offset 9
  2862. :args ((group :sibling-args (:help-echo "\
  2863. Only match the specified window systems.")
  2864. (const :format "Type: "
  2865. type)
  2866. (checklist :inline t
  2867. :offset 0
  2868. (const :format "X "
  2869. :sibling-args (:help-echo "\
  2870. The X11 Window System.")
  2871. x)
  2872. (const :format "PM "
  2873. :sibling-args (:help-echo "\
  2874. OS/2 Presentation Manager.")
  2875. pm)
  2876. (const :format "W32 "
  2877. :sibling-args (:help-echo "\
  2878. MS Windows.")
  2879. w32)
  2880. (const :format "NS "
  2881. :sibling-args (:help-echo "\
  2882. GNUstep or Macintosh OS Cocoa interface.")
  2883. ns)
  2884. (const :format "DOS "
  2885. :sibling-args (:help-echo "\
  2886. Plain MS-DOS.")
  2887. pc)
  2888. (const :format "TTY%n"
  2889. :sibling-args (:help-echo "\
  2890. Plain text terminals.")
  2891. tty)))
  2892. (group :sibling-args (:help-echo "\
  2893. Only match the frames with the specified color support.")
  2894. (const :format "Class: "
  2895. class)
  2896. (checklist :inline t
  2897. :offset 0
  2898. (const :format "Color "
  2899. :sibling-args (:help-echo "\
  2900. Match color frames.")
  2901. color)
  2902. (const :format "Grayscale "
  2903. :sibling-args (:help-echo "\
  2904. Match grayscale frames.")
  2905. grayscale)
  2906. (const :format "Monochrome%n"
  2907. :sibling-args (:help-echo "\
  2908. Match frames with no color support.")
  2909. mono)))
  2910. (group :sibling-args (:help-echo "\
  2911. The minimum number of colors the frame should support.")
  2912. (const :format "" min-colors)
  2913. (integer :tag "Minimum number of colors" ))
  2914. (group :sibling-args (:help-echo "\
  2915. Only match frames with the specified intensity.")
  2916. (const :format "\
  2917. Background brightness: "
  2918. background)
  2919. (checklist :inline t
  2920. :offset 0
  2921. (const :format "Light "
  2922. :sibling-args (:help-echo "\
  2923. Match frames with light backgrounds.")
  2924. light)
  2925. (const :format "Dark\n"
  2926. :sibling-args (:help-echo "\
  2927. Match frames with dark backgrounds.")
  2928. dark)))
  2929. (group :sibling-args (:help-echo "\
  2930. Only match frames that support the specified face attributes.")
  2931. (const :format "Supports attributes:" supports)
  2932. (custom-face-edit :inline t :format "%n%v"))))))
  2933. ;;; The `custom-face' Widget.
  2934. (defface custom-face-tag
  2935. '((t :inherit custom-variable-tag))
  2936. "Face used for face tags."
  2937. :group 'custom-faces)
  2938. (defcustom custom-face-default-form 'selected
  2939. "Default form of displaying face definition."
  2940. :type '(choice (const all)
  2941. (const selected)
  2942. (const lisp))
  2943. :group 'custom-buffer
  2944. :version "20.3")
  2945. (define-widget 'custom-face 'custom
  2946. "Widget for customizing a face.
  2947. The following properties have special meanings for this widget:
  2948. :value is the face name (a symbol).
  2949. :custom-form should be a symbol describing how to display and
  2950. edit the face attributes---either `selected' (attributes for
  2951. selected display only), `all' (all attributes), `lisp' (as a
  2952. Lisp sexp), or `mismatch' (should not happen); if nil, use
  2953. the return value of `custom-face-default-form'.
  2954. :custom-style describes the widget interface style; nil is the
  2955. default style, while `simple' means a simpler interface that
  2956. inhibits the magic custom-state widget.
  2957. :sample-indent, if non-nil, is the number of columns to which to
  2958. indent the face sample (an integer).
  2959. :shown-value, if non-nil, is the face spec to display as the value
  2960. of the widget, instead of the current face spec."
  2961. :sample-face 'custom-face-tag
  2962. :help-echo "Set or reset this face."
  2963. :documentation-property #'face-doc-string
  2964. :value-create 'custom-face-value-create
  2965. :action 'custom-face-action
  2966. :custom-category 'face
  2967. :custom-form nil
  2968. :custom-set 'custom-face-set
  2969. :custom-mark-to-save 'custom-face-mark-to-save
  2970. :custom-reset-current 'custom-redraw
  2971. :custom-reset-saved 'custom-face-reset-saved
  2972. :custom-reset-standard 'custom-face-reset-standard
  2973. :custom-mark-to-reset-standard 'custom-face-mark-to-reset-standard
  2974. :custom-standard-value 'custom-face-standard-value
  2975. :custom-state-set-and-redraw 'custom-face-state-set-and-redraw
  2976. :custom-menu 'custom-face-menu-create)
  2977. (define-widget 'custom-face-all 'editable-list
  2978. "An editable list of display specifications and attributes."
  2979. :entry-format "%i %d %v"
  2980. :insert-button-args '(:help-echo "Insert new display specification here.")
  2981. :append-button-args '(:help-echo "Append new display specification here.")
  2982. :delete-button-args '(:help-echo "Delete this display specification.")
  2983. :args '((group :format "%v" custom-display custom-face-edit)))
  2984. (defconst custom-face-all (widget-convert 'custom-face-all)
  2985. "Converted version of the `custom-face-all' widget.")
  2986. (defun custom-filter-face-spec (spec filter-index &optional default-filter)
  2987. "Return a canonicalized version of SPEC.
  2988. FILTER-INDEX is the index in the entry for each attribute in
  2989. `custom-face-attributes' at which the appropriate filter function can be
  2990. found, and DEFAULT-FILTER is the filter to apply for attributes that
  2991. don't specify one."
  2992. (mapcar (lambda (entry)
  2993. ;; Filter a single face-spec entry
  2994. (let ((tests (car entry))
  2995. (unfiltered-attrs
  2996. ;; Handle both old- and new-style attribute syntax
  2997. (if (listp (car (cdr entry)))
  2998. (car (cdr entry))
  2999. (cdr entry)))
  3000. (filtered-attrs nil))
  3001. ;; Filter each face attribute
  3002. (while unfiltered-attrs
  3003. (let* ((attr (pop unfiltered-attrs))
  3004. (pre-filtered-value (pop unfiltered-attrs))
  3005. (filter
  3006. (or (nth filter-index (assq attr custom-face-attributes))
  3007. default-filter))
  3008. (filtered-value
  3009. (if filter
  3010. (funcall filter pre-filtered-value)
  3011. pre-filtered-value)))
  3012. (push filtered-value filtered-attrs)
  3013. (push attr filtered-attrs)))
  3014. ;;
  3015. (list tests filtered-attrs)))
  3016. spec))
  3017. (defun custom-pre-filter-face-spec (spec)
  3018. "Return SPEC changed as necessary for editing by the face customization widget.
  3019. SPEC must be a full face spec."
  3020. (custom-filter-face-spec spec 2))
  3021. (defun custom-post-filter-face-spec (spec)
  3022. "Return the customized SPEC in a form suitable for setting the face."
  3023. (custom-filter-face-spec spec 3))
  3024. (defun custom-face-widget-to-spec (widget)
  3025. "Return a face spec corresponding to WIDGET.
  3026. WIDGET should be a `custom-face' widget."
  3027. (unless (eq (widget-type widget) 'custom-face)
  3028. (error "Invalid widget"))
  3029. (let ((child (car (widget-get widget :children))))
  3030. (custom-post-filter-face-spec
  3031. (if (eq (widget-type child) 'custom-face-edit)
  3032. `((t ,(widget-value child)))
  3033. (widget-value child)))))
  3034. (defun custom-face-get-current-spec (face)
  3035. (let ((spec (or (get face 'customized-face)
  3036. (get face 'saved-face)
  3037. (get face 'face-defface-spec)
  3038. ;; Attempt to construct it.
  3039. `((t ,(custom-face-attributes-get
  3040. face (selected-frame)))))))
  3041. ;; If the user has changed this face in some other way,
  3042. ;; edit it as the user has specified it.
  3043. (if (not (face-spec-match-p face spec (selected-frame)))
  3044. (setq spec `((t ,(face-attr-construct face (selected-frame))))))
  3045. (custom-pre-filter-face-spec spec)))
  3046. (defun custom-toggle-hide-face (visibility-widget &rest _ignore)
  3047. "Toggle the visibility of a `custom-face' parent widget.
  3048. By default, this signals an error if the parent has unsaved
  3049. changes. If the parent has a `simple' :custom-style property,
  3050. the present value is saved to its :shown-value property instead."
  3051. (let ((widget (widget-get visibility-widget :parent)))
  3052. (unless (eq (widget-type widget) 'custom-face)
  3053. (error "Invalid widget type"))
  3054. (custom-load-widget widget)
  3055. (let ((state (widget-get widget :custom-state)))
  3056. (if (eq state 'hidden)
  3057. (widget-put widget :custom-state 'unknown)
  3058. ;; In normal interface, widget can't be hidden if modified.
  3059. (when (memq state '(invalid modified set))
  3060. (if (eq (widget-get widget :custom-style) 'simple)
  3061. (widget-put widget :shown-value
  3062. (custom-face-widget-to-spec widget))
  3063. (error "There are unsaved changes")))
  3064. (widget-put widget :documentation-shown nil)
  3065. (widget-put widget :custom-state 'hidden))
  3066. (custom-redraw widget)
  3067. (widget-setup))))
  3068. (defun custom-face-value-create (widget)
  3069. "Create a list of the display specifications for WIDGET."
  3070. (let* ((buttons (widget-get widget :buttons))
  3071. (symbol (widget-get widget :value))
  3072. (tag (or (widget-get widget :tag)
  3073. (prin1-to-string symbol)))
  3074. (hiddenp (eq (widget-get widget :custom-state) 'hidden))
  3075. (style (widget-get widget :custom-style))
  3076. children)
  3077. (if (eq custom-buffer-style 'tree)
  3078. ;; Draw a tree-style `custom-face' widget
  3079. (progn
  3080. (insert (widget-get widget :custom-prefix)
  3081. (if (widget-get widget :custom-last) " `--- " " |--- "))
  3082. (push (widget-create-child-and-convert
  3083. widget 'custom-browse-face-tag)
  3084. buttons)
  3085. (insert " " tag "\n")
  3086. (widget-put widget :buttons buttons))
  3087. ;; Draw an ordinary `custom-face' widget
  3088. (let ((opoint (point)))
  3089. ;; Visibility indicator.
  3090. (push (widget-create-child-and-convert
  3091. widget 'custom-visibility
  3092. :help-echo "Hide or show this face."
  3093. :on "Hide" :off "Show"
  3094. :on-glyph "down" :off-glyph "right"
  3095. :action 'custom-toggle-hide-face
  3096. (not hiddenp))
  3097. buttons)
  3098. ;; Face name (tag).
  3099. (insert " " tag)
  3100. (widget-specify-sample widget opoint (point)))
  3101. (insert
  3102. (cond ((eq custom-buffer-style 'face) " ")
  3103. ((string-match-p "face\\'" tag) ":")
  3104. (t " face: ")))
  3105. ;; Face sample.
  3106. (let ((sample-indent (widget-get widget :sample-indent))
  3107. (indent-tabs-mode nil))
  3108. (and sample-indent
  3109. (<= (current-column) sample-indent)
  3110. (indent-to-column sample-indent)))
  3111. (push (widget-create-child-and-convert
  3112. widget 'item
  3113. :format "[%{%t%}]"
  3114. :sample-face (let ((spec (widget-get widget :shown-value)))
  3115. (if spec (face-spec-choose spec) symbol))
  3116. :tag "sample")
  3117. buttons)
  3118. (insert "\n")
  3119. ;; Magic.
  3120. (unless (eq (widget-get widget :custom-style) 'simple)
  3121. (let ((magic (widget-create-child-and-convert
  3122. widget 'custom-magic nil)))
  3123. (widget-put widget :custom-magic magic)
  3124. (push magic buttons)))
  3125. ;; Update buttons.
  3126. (widget-put widget :buttons buttons)
  3127. ;; Insert documentation.
  3128. (unless (and hiddenp (eq style 'simple))
  3129. (widget-put widget :documentation-indent 3)
  3130. (widget-add-documentation-string-button
  3131. widget :visibility-widget 'custom-visibility)
  3132. ;; The comment field
  3133. (unless hiddenp
  3134. (let* ((comment (get symbol 'face-comment))
  3135. (comment-widget
  3136. (widget-create-child-and-convert
  3137. widget 'custom-comment
  3138. :parent widget
  3139. :value (or comment ""))))
  3140. (widget-put widget :comment-widget comment-widget)
  3141. (push comment-widget children))))
  3142. ;; Editor.
  3143. (unless (eq (preceding-char) ?\n)
  3144. (insert "\n"))
  3145. (unless hiddenp
  3146. (custom-load-widget widget)
  3147. (unless (widget-get widget :custom-form)
  3148. (widget-put widget :custom-form custom-face-default-form))
  3149. (let* ((spec (or (widget-get widget :shown-value)
  3150. (custom-face-get-current-spec symbol)))
  3151. (form (widget-get widget :custom-form))
  3152. (indent (widget-get widget :indent))
  3153. face-alist face-entry spec-default spec-match editor)
  3154. ;; Find a display in SPEC matching the selected display.
  3155. ;; This will use the usual face customization interface.
  3156. (setq face-alist spec)
  3157. (when (eq (car-safe (car-safe face-alist)) 'default)
  3158. (setq spec-default (pop face-alist)))
  3159. (while (and face-alist (listp face-alist) (null spec-match))
  3160. (setq face-entry (car face-alist))
  3161. (and (listp face-entry)
  3162. (face-spec-set-match-display (car face-entry)
  3163. (selected-frame))
  3164. (widget-apply custom-face-edit :match (cadr face-entry))
  3165. (setq spec-match face-entry))
  3166. (setq face-alist (cdr face-alist)))
  3167. ;; Insert the appropriate editing widget.
  3168. (setq editor
  3169. (cond
  3170. ((and (eq form 'selected)
  3171. (or spec-match spec-default))
  3172. (when indent (insert-char ?\s indent))
  3173. (widget-create-child-and-convert
  3174. widget 'custom-face-edit
  3175. :value (cadr spec-match)
  3176. :default-face-attributes (cadr spec-default)))
  3177. ((and (not (eq form 'lisp))
  3178. (widget-apply custom-face-all :match spec))
  3179. (widget-create-child-and-convert
  3180. widget 'custom-face-all :value spec))
  3181. (t
  3182. (when indent
  3183. (insert-char ?\s indent))
  3184. (widget-create-child-and-convert
  3185. widget 'sexp :value spec))))
  3186. (custom-face-state-set widget)
  3187. (push editor children)
  3188. (widget-put widget :children children))))))
  3189. (defvar custom-face-menu
  3190. `(("Set for Current Session" custom-face-set)
  3191. ,@(when (or custom-file init-file-user)
  3192. '(("Save for Future Sessions" custom-face-save)))
  3193. ("Undo Edits" custom-redraw
  3194. (lambda (widget)
  3195. (memq (widget-get widget :custom-state) '(modified changed))))
  3196. ("Revert This Session's Customization" custom-face-reset-saved
  3197. (lambda (widget)
  3198. (memq (widget-get widget :custom-state) '(modified set changed))))
  3199. ,@(when (or custom-file init-file-user)
  3200. '(("Erase Customization" custom-face-reset-standard
  3201. (lambda (widget)
  3202. (get (widget-value widget) 'face-defface-spec)))))
  3203. ("---" ignore ignore)
  3204. ("Add Comment" custom-comment-show custom-comment-invisible-p)
  3205. ("---" ignore ignore)
  3206. ("For Current Display" custom-face-edit-selected
  3207. (lambda (widget)
  3208. (not (eq (widget-get widget :custom-form) 'selected))))
  3209. ("For All Kinds of Displays" custom-face-edit-all
  3210. (lambda (widget)
  3211. (not (eq (widget-get widget :custom-form) 'all))))
  3212. ("Show Lisp Expression" custom-face-edit-lisp
  3213. (lambda (widget)
  3214. (not (eq (widget-get widget :custom-form) 'lisp)))))
  3215. "Alist of actions for the `custom-face' widget.
  3216. Each entry has the form (NAME ACTION FILTER) where NAME is the name of
  3217. the menu entry, ACTION is the function to call on the widget when the
  3218. menu is selected, and FILTER is a predicate which takes a `custom-face'
  3219. widget as an argument, and returns non-nil if ACTION is valid on that
  3220. widget. If FILTER is nil, ACTION is always valid.")
  3221. (defun custom-face-edit-selected (widget)
  3222. "Edit selected attributes of the value of WIDGET."
  3223. (widget-put widget :custom-state 'unknown)
  3224. (widget-put widget :custom-form 'selected)
  3225. (custom-redraw widget))
  3226. (defun custom-face-edit-all (widget)
  3227. "Edit all attributes of the value of WIDGET."
  3228. (widget-put widget :custom-state 'unknown)
  3229. (widget-put widget :custom-form 'all)
  3230. (custom-redraw widget))
  3231. (defun custom-face-edit-lisp (widget)
  3232. "Edit the Lisp representation of the value of WIDGET."
  3233. (widget-put widget :custom-state 'unknown)
  3234. (widget-put widget :custom-form 'lisp)
  3235. (custom-redraw widget))
  3236. (defun custom-face-state (face)
  3237. "Return the current state of the face FACE.
  3238. This is one of `set', `saved', `changed', `themed', or `rogue'."
  3239. (let* ((comment (get face 'face-comment))
  3240. (state
  3241. (cond
  3242. ((or (get face 'customized-face)
  3243. (get face 'customized-face-comment))
  3244. (if (equal (get face 'customized-face-comment) comment)
  3245. 'set
  3246. 'changed))
  3247. ((or (get face 'saved-face)
  3248. (get face 'saved-face-comment))
  3249. (cond ((not (equal (get face 'saved-face-comment) comment))
  3250. 'changed)
  3251. ((eq 'user (caar (get face 'theme-face)))
  3252. 'saved)
  3253. ((eq 'changed (caar (get face 'theme-face)))
  3254. 'changed)
  3255. (t 'themed)))
  3256. ((get face 'face-defface-spec)
  3257. (cond (comment 'changed)
  3258. ((get face 'theme-face) 'themed)
  3259. (t 'standard)))
  3260. (t 'rogue))))
  3261. ;; If the user called set-face-attribute to change the default for
  3262. ;; new frames, this face is "set outside of Customize".
  3263. (if (and (not (eq state 'rogue))
  3264. (get face 'face-modified))
  3265. 'changed
  3266. state)))
  3267. (defun custom-face-state-set (widget)
  3268. "Set the state of WIDGET."
  3269. (widget-put widget :custom-state
  3270. (custom-face-state (widget-value widget))))
  3271. (defun custom-face-action (widget &optional event)
  3272. "Show the menu for `custom-face' WIDGET.
  3273. Optional EVENT is the location for the menu."
  3274. (if (eq (widget-get widget :custom-state) 'hidden)
  3275. (custom-toggle-hide widget)
  3276. (let* ((completion-ignore-case t)
  3277. (symbol (widget-get widget :value))
  3278. (answer (widget-choose (concat "Operation on "
  3279. (custom-unlispify-tag-name symbol))
  3280. (custom-menu-filter custom-face-menu
  3281. widget)
  3282. event)))
  3283. (if answer
  3284. (funcall answer widget)))))
  3285. (defun custom-face-set (widget)
  3286. "Make the face attributes in WIDGET take effect."
  3287. (let* ((symbol (widget-value widget))
  3288. (value (custom-face-widget-to-spec widget))
  3289. (comment-widget (widget-get widget :comment-widget))
  3290. (comment (widget-value comment-widget)))
  3291. (when (equal comment "")
  3292. (setq comment nil)
  3293. ;; Make the comment invisible by hand if it's empty
  3294. (custom-comment-hide comment-widget))
  3295. (custom-push-theme 'theme-face symbol 'user 'set value)
  3296. (face-spec-set symbol value 'customized-face)
  3297. (put symbol 'face-comment comment)
  3298. (put symbol 'customized-face-comment comment)
  3299. (custom-face-state-set widget)
  3300. (custom-redraw-magic widget)))
  3301. (defun custom-face-mark-to-save (widget)
  3302. "Mark for saving the face edited by WIDGET."
  3303. (let* ((symbol (widget-value widget))
  3304. (value (custom-face-widget-to-spec widget))
  3305. (comment-widget (widget-get widget :comment-widget))
  3306. (comment (widget-value comment-widget))
  3307. (standard (eq (widget-get widget :custom-state) 'standard)))
  3308. (when (equal comment "")
  3309. (setq comment nil)
  3310. ;; Make the comment invisible by hand if it's empty
  3311. (custom-comment-hide comment-widget))
  3312. (custom-push-theme 'theme-face symbol 'user 'set value)
  3313. (face-spec-set symbol value (if standard 'reset 'saved-face))
  3314. (put symbol 'face-comment comment)
  3315. (put symbol 'customized-face-comment nil)
  3316. (put symbol 'saved-face-comment comment)))
  3317. (defsubst custom-face-state-set-and-redraw (widget)
  3318. "Set state of face widget WIDGET and redraw with current settings."
  3319. (custom-face-state-set widget)
  3320. (custom-redraw-magic widget))
  3321. (defun custom-face-save (widget)
  3322. "Save the face edited by WIDGET."
  3323. (custom-face-mark-to-save widget)
  3324. (custom-save-all)
  3325. (custom-face-state-set-and-redraw widget))
  3326. ;; For backward compatibility.
  3327. (define-obsolete-function-alias 'custom-face-save-command 'custom-face-save
  3328. "22.1")
  3329. (defun custom-face-reset-saved (widget)
  3330. "Restore WIDGET to the face's default attributes.
  3331. If there is a saved face, restore it; otherwise reset to the
  3332. uncustomized (themed or standard) face."
  3333. (let* ((face (widget-value widget))
  3334. (child (car (widget-get widget :children)))
  3335. (saved-face (get face 'saved-face))
  3336. (comment (get face 'saved-face-comment))
  3337. (comment-widget (widget-get widget :comment-widget)))
  3338. (custom-push-theme 'theme-face face 'user
  3339. (if saved-face 'set 'reset)
  3340. saved-face)
  3341. (face-spec-set face saved-face 'saved-face)
  3342. (put face 'face-comment comment)
  3343. (put face 'customized-face-comment nil)
  3344. (widget-value-set child saved-face)
  3345. ;; This call manages the comment visibility
  3346. (widget-value-set comment-widget (or comment ""))
  3347. (custom-face-state-set widget)
  3348. (custom-redraw widget)))
  3349. (defun custom-face-standard-value (widget)
  3350. (get (widget-value widget) 'face-defface-spec))
  3351. (defun custom-face-mark-to-reset-standard (widget)
  3352. "Restore widget WIDGET to the face's standard attribute values.
  3353. If `custom-reset-standard-faces-list' is nil, save, reset and
  3354. redraw the widget immediately."
  3355. (let* ((symbol (widget-value widget))
  3356. (child (car (widget-get widget :children)))
  3357. (value (get symbol 'face-defface-spec))
  3358. (comment-widget (widget-get widget :comment-widget)))
  3359. (unless value
  3360. (user-error "No standard setting for this face"))
  3361. (custom-push-theme 'theme-face symbol 'user 'reset)
  3362. (face-spec-set symbol value 'reset)
  3363. (put symbol 'face-comment nil)
  3364. (put symbol 'customized-face-comment nil)
  3365. (if (and custom-reset-standard-faces-list
  3366. (or (get symbol 'saved-face) (get symbol 'saved-face-comment)))
  3367. ;; Do this later.
  3368. (progn
  3369. (put symbol 'saved-face nil)
  3370. (put symbol 'saved-face-comment nil)
  3371. ;; Append this to `custom-reset-standard-faces-list' and have
  3372. ;; `custom-reset-standard-save-and-update' save setting to the
  3373. ;; file, update the widget's state, and redraw it.
  3374. (setq custom-reset-standard-faces-list
  3375. (cons widget custom-reset-standard-faces-list)))
  3376. (when (or (get symbol 'saved-face) (get symbol 'saved-face-comment))
  3377. (put symbol 'saved-face nil)
  3378. (put symbol 'saved-face-comment nil)
  3379. (custom-save-all))
  3380. (widget-value-set child
  3381. (custom-pre-filter-face-spec
  3382. (list (list t (custom-face-attributes-get
  3383. symbol nil)))))
  3384. ;; This call manages the comment visibility
  3385. (widget-value-set comment-widget "")
  3386. (custom-face-state-set widget)
  3387. (custom-redraw-magic widget))))
  3388. (defun custom-face-reset-standard (widget)
  3389. "Restore WIDGET to the face's standard attribute values.
  3390. This operation eliminates any saved attributes for the face,
  3391. restoring it to the state of a face that has never been customized."
  3392. (let (custom-reset-standard-faces-list)
  3393. (custom-face-mark-to-reset-standard widget)))
  3394. ;;; The `face' Widget.
  3395. (defvar widget-face-prompt-value-history nil
  3396. "History of input to `widget-face-prompt-value'.")
  3397. (define-widget 'face 'symbol
  3398. "A Lisp face name (with sample)."
  3399. :format "%{%t%}: (%{sample%}) %v"
  3400. :tag "Face"
  3401. :value 'default
  3402. :sample-face-get 'widget-face-sample-face-get
  3403. :notify 'widget-face-notify
  3404. :match (lambda (_widget value) (facep value))
  3405. :completions (apply-partially #'completion-table-with-predicate
  3406. obarray #'facep 'strict)
  3407. :prompt-match 'facep
  3408. :prompt-history 'widget-face-prompt-value-history
  3409. :validate (lambda (widget)
  3410. (unless (facep (widget-value widget))
  3411. (widget-put widget
  3412. :error (format "Invalid face: %S"
  3413. (widget-value widget)))
  3414. widget)))
  3415. (defun widget-face-sample-face-get (widget)
  3416. (let ((value (widget-value widget)))
  3417. (if (facep value)
  3418. value
  3419. 'default)))
  3420. (defun widget-face-notify (widget child &optional event)
  3421. "Update the sample, and notify the parent."
  3422. (overlay-put (widget-get widget :sample-overlay)
  3423. 'face (widget-apply widget :sample-face-get))
  3424. (widget-default-notify widget child event))
  3425. ;;; The `hook' Widget.
  3426. (define-widget 'hook 'list
  3427. "An Emacs Lisp hook."
  3428. :value-to-internal (lambda (_widget value)
  3429. (if (and value (symbolp value))
  3430. (list value)
  3431. value))
  3432. :match (lambda (widget value)
  3433. (or (symbolp value)
  3434. (widget-group-match widget value)))
  3435. ;; Avoid adding undefined functions to the hook, especially for
  3436. ;; things like `find-file-hook' or even more basic ones, to avoid
  3437. ;; chaos.
  3438. :set (lambda (symbol value)
  3439. (dolist (elt value)
  3440. (if (fboundp elt)
  3441. (add-hook symbol elt))))
  3442. :convert-widget 'custom-hook-convert-widget
  3443. :tag "Hook")
  3444. (defun custom-hook-convert-widget (widget)
  3445. ;; Handle `:options'.
  3446. (let* ((options (widget-get widget :options))
  3447. (other `(editable-list :inline t
  3448. :entry-format "%i %d%v"
  3449. (function :format " %v")))
  3450. (args (if options
  3451. (list `(checklist :inline t
  3452. ,@(mapcar (lambda (entry)
  3453. `(function-item ,entry))
  3454. options))
  3455. other)
  3456. (list other))))
  3457. (widget-put widget :args args)
  3458. widget))
  3459. ;;; The `custom-group-link' Widget.
  3460. (define-widget 'custom-group-link 'link
  3461. "Show parent in other window when activated."
  3462. :button-face 'custom-link
  3463. :mouse-face 'highlight
  3464. :pressed-face 'highlight
  3465. :help-echo "Create customization buffer for this group."
  3466. :keymap custom-mode-link-map
  3467. :follow-link 'mouse-face
  3468. :action 'custom-group-link-action)
  3469. (defun custom-group-link-action (widget &rest _ignore)
  3470. (customize-group (widget-value widget)))
  3471. ;;; The `custom-group' Widget.
  3472. (defcustom custom-group-tag-faces nil
  3473. "Face used for group tags.
  3474. The first member is used for level 1 groups, the second for level 2,
  3475. and so forth. The remaining group tags are shown with `custom-group-tag'."
  3476. :type '(repeat face)
  3477. :group 'custom-faces)
  3478. (defface custom-group-tag-1
  3479. '((default :weight bold :height 1.2 :inherit variable-pitch)
  3480. (((class color) (background dark)) :foreground "pink")
  3481. (((min-colors 88) (class color) (background light)) :foreground "red1")
  3482. (((class color) (background light)) :foreground "red"))
  3483. "Face for group tags."
  3484. :group 'custom-faces)
  3485. (defface custom-group-tag
  3486. '((default :weight bold :height 1.2 :inherit variable-pitch)
  3487. (((class color) (background dark)) :foreground "light blue")
  3488. (((min-colors 88) (class color) (background light)) :foreground "blue1")
  3489. (((class color) (background light)) :foreground "blue")
  3490. (t :weight bold))
  3491. "Face for low level group tags."
  3492. :group 'custom-faces)
  3493. (defface custom-group-subtitle
  3494. '((t :weight bold))
  3495. "Face for the \"Subgroups:\" subtitle in Custom buffers."
  3496. :group 'custom-faces)
  3497. (defvar custom-group-doc-align-col 20)
  3498. (define-widget 'custom-group 'custom
  3499. "Customize group."
  3500. :format "%v"
  3501. :sample-face-get 'custom-group-sample-face-get
  3502. :documentation-property 'group-documentation
  3503. :help-echo "Set or reset all members of this group."
  3504. :value-create 'custom-group-value-create
  3505. :action 'custom-group-action
  3506. :custom-category 'group
  3507. :custom-set 'custom-group-set
  3508. :custom-mark-to-save 'custom-group-mark-to-save
  3509. :custom-reset-current 'custom-group-reset-current
  3510. :custom-reset-saved 'custom-group-reset-saved
  3511. :custom-reset-standard 'custom-group-reset-standard
  3512. :custom-mark-to-reset-standard 'custom-group-mark-to-reset-standard
  3513. :custom-state-set-and-redraw 'custom-group-state-set-and-redraw
  3514. :custom-menu 'custom-group-menu-create)
  3515. (defun custom-group-sample-face-get (widget)
  3516. ;; Use :sample-face.
  3517. (or (nth (1- (widget-get widget :custom-level)) custom-group-tag-faces)
  3518. 'custom-group-tag))
  3519. (define-widget 'custom-group-visibility 'visibility
  3520. "An indicator and manipulator for hidden group contents."
  3521. :create 'custom-group-visibility-create)
  3522. (defun custom-group-visibility-create (widget)
  3523. (let ((visible (widget-value widget)))
  3524. (if visible
  3525. (insert "--------")))
  3526. (widget-default-create widget))
  3527. (defun custom-group-members (symbol groups-only)
  3528. "Return SYMBOL's custom group members.
  3529. If GROUPS-ONLY is non-nil, return only those members that are groups."
  3530. (if (not groups-only)
  3531. (get symbol 'custom-group)
  3532. (let (members)
  3533. (dolist (entry (get symbol 'custom-group))
  3534. (when (eq (nth 1 entry) 'custom-group)
  3535. (push entry members)))
  3536. (nreverse members))))
  3537. (defun custom-group-value-create (widget)
  3538. "Insert a customize group for WIDGET in the current buffer."
  3539. (unless (eq (widget-get widget :custom-state) 'hidden)
  3540. (custom-load-widget widget))
  3541. (let* ((state (widget-get widget :custom-state))
  3542. (level (widget-get widget :custom-level))
  3543. ;; (indent (widget-get widget :indent))
  3544. (prefix (widget-get widget :custom-prefix))
  3545. (buttons (widget-get widget :buttons))
  3546. (tag (substitute-command-keys (widget-get widget :tag)))
  3547. (symbol (widget-value widget))
  3548. (members (custom-group-members symbol
  3549. (and (eq custom-buffer-style 'tree)
  3550. custom-browse-only-groups)))
  3551. (doc (substitute-command-keys (widget-docstring widget))))
  3552. (cond ((and (eq custom-buffer-style 'tree)
  3553. (eq state 'hidden)
  3554. (or members (custom-unloaded-widget-p widget)))
  3555. (custom-browse-insert-prefix prefix)
  3556. (push (widget-create-child-and-convert
  3557. widget 'custom-browse-visibility
  3558. :tag "+")
  3559. buttons)
  3560. (insert "-- ")
  3561. (push (widget-create-child-and-convert
  3562. widget 'custom-browse-group-tag)
  3563. buttons)
  3564. (insert " " tag "\n")
  3565. (widget-put widget :buttons buttons))
  3566. ((and (eq custom-buffer-style 'tree)
  3567. (zerop (length members)))
  3568. (custom-browse-insert-prefix prefix)
  3569. (insert "[ ]-- ")
  3570. (push (widget-create-child-and-convert
  3571. widget 'custom-browse-group-tag)
  3572. buttons)
  3573. (insert " " tag "\n")
  3574. (widget-put widget :buttons buttons))
  3575. ((eq custom-buffer-style 'tree)
  3576. (custom-browse-insert-prefix prefix)
  3577. (if (zerop (length members))
  3578. (progn
  3579. (custom-browse-insert-prefix prefix)
  3580. (insert "[ ]-- ")
  3581. ;; (widget-glyph-insert nil "[ ]" "empty")
  3582. ;; (widget-glyph-insert nil "-- " "horizontal")
  3583. (push (widget-create-child-and-convert
  3584. widget 'custom-browse-group-tag)
  3585. buttons)
  3586. (insert " " tag "\n")
  3587. (widget-put widget :buttons buttons))
  3588. (push (widget-create-child-and-convert
  3589. widget 'custom-browse-visibility
  3590. ;; :tag-glyph "minus"
  3591. :tag "-")
  3592. buttons)
  3593. (insert "-\\ ")
  3594. ;; (widget-glyph-insert nil "-\\ " "top")
  3595. (push (widget-create-child-and-convert
  3596. widget 'custom-browse-group-tag)
  3597. buttons)
  3598. (insert " " tag "\n")
  3599. (widget-put widget :buttons buttons)
  3600. (message "Creating group...")
  3601. (let* ((members (custom-sort-items
  3602. members
  3603. ;; Never sort the top-level custom group.
  3604. (unless (eq symbol 'emacs)
  3605. custom-browse-sort-alphabetically)
  3606. custom-browse-order-groups))
  3607. (prefixes (widget-get widget :custom-prefixes))
  3608. (custom-prefix-list (custom-prefix-add symbol prefixes))
  3609. (extra-prefix (if (widget-get widget :custom-last)
  3610. " "
  3611. " | "))
  3612. (prefix (concat prefix extra-prefix))
  3613. children entry)
  3614. (while members
  3615. (setq entry (car members)
  3616. members (cdr members))
  3617. (push (widget-create-child-and-convert
  3618. widget (nth 1 entry)
  3619. :group widget
  3620. :tag (custom-unlispify-tag-name (nth 0 entry))
  3621. :custom-prefixes custom-prefix-list
  3622. :custom-level (1+ level)
  3623. :custom-last (null members)
  3624. :value (nth 0 entry)
  3625. :custom-prefix prefix)
  3626. children))
  3627. (widget-put widget :children (reverse children)))
  3628. (message "Creating group...done")))
  3629. ;; Nested style.
  3630. ((eq state 'hidden)
  3631. ;; Create level indicator.
  3632. ;; Create tag.
  3633. (if (eq custom-buffer-style 'links)
  3634. (push (widget-create-child-and-convert
  3635. widget 'custom-group-link
  3636. :tag tag
  3637. symbol)
  3638. buttons)
  3639. (insert-char ?\s (* custom-buffer-indent (1- level)))
  3640. (insert "-- ")
  3641. (push (widget-create-child-and-convert
  3642. widget 'custom-group-visibility
  3643. :help-echo "Show members of this group."
  3644. :action 'custom-toggle-parent
  3645. (not (eq state 'hidden)))
  3646. buttons))
  3647. (if (>= (current-column) custom-group-doc-align-col)
  3648. (insert " "))
  3649. ;; Create magic button.
  3650. (let ((magic (widget-create-child-and-convert
  3651. widget 'custom-magic nil)))
  3652. (widget-put widget :custom-magic magic)
  3653. (push magic buttons))
  3654. ;; Update buttons.
  3655. (widget-put widget :buttons buttons)
  3656. ;; Insert documentation.
  3657. (if (and (eq custom-buffer-style 'links) (> level 1))
  3658. (widget-put widget :documentation-indent
  3659. custom-group-doc-align-col))
  3660. (widget-add-documentation-string-button
  3661. widget :visibility-widget 'custom-visibility))
  3662. ;; Nested style.
  3663. (t ;Visible.
  3664. ;; Draw a horizontal line (this works for both graphical
  3665. ;; and text displays):
  3666. (let ((p (point)))
  3667. (insert "\n")
  3668. (put-text-property p (1+ p) 'face '(:underline t))
  3669. (overlay-put (make-overlay p (1+ p))
  3670. 'before-string
  3671. (propertize "\n" 'face '(:underline t)
  3672. 'display '(space :align-to 999))))
  3673. ;; Add parent groups references above the group.
  3674. (when (eq level 1)
  3675. (if (custom-add-parent-links widget "Parent groups:")
  3676. (insert "\n")))
  3677. (insert-char ?\s (* custom-buffer-indent (1- level)))
  3678. ;; Create tag.
  3679. (let ((start (point)))
  3680. (insert tag " group: ")
  3681. (widget-specify-sample widget start (point)))
  3682. (cond
  3683. ((not doc)
  3684. (insert " Group definition missing. "))
  3685. ((< (length doc) 50)
  3686. (insert doc)))
  3687. ;; Create visibility indicator.
  3688. (unless (eq custom-buffer-style 'links)
  3689. (insert "--------")
  3690. (push (widget-create-child-and-convert
  3691. widget 'visibility
  3692. :help-echo "Hide members of this group."
  3693. :action 'custom-toggle-parent
  3694. (not (eq state 'hidden)))
  3695. buttons)
  3696. (insert " "))
  3697. (insert "\n")
  3698. ;; Create magic button.
  3699. (let ((magic (widget-create-child-and-convert
  3700. widget 'custom-magic
  3701. :indent 0
  3702. nil)))
  3703. (widget-put widget :custom-magic magic)
  3704. (push magic buttons))
  3705. ;; Update buttons.
  3706. (widget-put widget :buttons buttons)
  3707. ;; Insert documentation.
  3708. (when (and doc (>= (length doc) 50))
  3709. (widget-add-documentation-string-button
  3710. widget :visibility-widget 'custom-visibility))
  3711. ;; Parent groups.
  3712. (if nil ;;; This should test that the buffer
  3713. ;;; was not made to display a group.
  3714. (when (eq level 1)
  3715. (insert-char ?\s custom-buffer-indent)
  3716. (custom-add-parent-links widget)))
  3717. (custom-add-see-also widget
  3718. (make-string (* custom-buffer-indent level)
  3719. ?\s))
  3720. ;; Members.
  3721. (message "Creating group...")
  3722. (let* ((members (custom-sort-items
  3723. members
  3724. ;; Never sort the top-level custom group.
  3725. (unless (eq symbol 'emacs)
  3726. custom-buffer-sort-alphabetically)
  3727. custom-buffer-order-groups))
  3728. (prefixes (widget-get widget :custom-prefixes))
  3729. (custom-prefix-list (custom-prefix-add symbol prefixes))
  3730. (len (length members))
  3731. (count 0)
  3732. (reporter (make-progress-reporter
  3733. "Creating group entries..." 0 len))
  3734. (have-subtitle (and (not (eq symbol 'emacs))
  3735. (eq custom-buffer-order-groups 'last)))
  3736. prev-type
  3737. children)
  3738. (dolist (entry members)
  3739. (unless (eq prev-type 'custom-group)
  3740. (widget-insert "\n"))
  3741. (progress-reporter-update reporter (setq count (1+ count)))
  3742. (let ((sym (nth 0 entry))
  3743. (type (nth 1 entry)))
  3744. (when (and have-subtitle (eq type 'custom-group))
  3745. (setq have-subtitle nil)
  3746. (widget-insert
  3747. (propertize "Subgroups:\n" 'face 'custom-group-subtitle)))
  3748. (setq prev-type type)
  3749. (push (widget-create-child-and-convert
  3750. widget type
  3751. :group widget
  3752. :tag (custom-unlispify-tag-name sym)
  3753. :custom-prefixes custom-prefix-list
  3754. :custom-level (1+ level)
  3755. :value sym)
  3756. children)
  3757. (unless (eq (preceding-char) ?\n)
  3758. (widget-insert "\n"))))
  3759. (setq children (nreverse children))
  3760. (mapc 'custom-magic-reset children)
  3761. (widget-put widget :children children)
  3762. (custom-group-state-update widget)
  3763. (progress-reporter-done reporter))
  3764. ;; End line
  3765. (let ((p (1+ (point))))
  3766. (insert "\n\n")
  3767. (put-text-property p (1+ p) 'face '(:underline t))
  3768. (overlay-put (make-overlay p (1+ p))
  3769. 'before-string
  3770. (propertize "\n" 'face '(:underline t)
  3771. 'display '(space :align-to 999))))))))
  3772. (defvar custom-group-menu
  3773. `(("Set for Current Session" custom-group-set
  3774. (lambda (widget)
  3775. (eq (widget-get widget :custom-state) 'modified)))
  3776. ,@(when (or custom-file init-file-user)
  3777. '(("Save for Future Sessions" custom-group-save
  3778. (lambda (widget)
  3779. (memq (widget-get widget :custom-state) '(modified set))))))
  3780. ("Undo Edits" custom-group-reset-current
  3781. (lambda (widget)
  3782. (memq (widget-get widget :custom-state) '(modified))))
  3783. ("Revert This Session's Customizations" custom-group-reset-saved
  3784. (lambda (widget)
  3785. (memq (widget-get widget :custom-state) '(modified set))))
  3786. ,@(when (or custom-file init-file-user)
  3787. '(("Erase Customization" custom-group-reset-standard
  3788. (lambda (widget)
  3789. (memq (widget-get widget :custom-state) '(modified set saved)))))))
  3790. "Alist of actions for the `custom-group' widget.
  3791. Each entry has the form (NAME ACTION FILTER) where NAME is the name of
  3792. the menu entry, ACTION is the function to call on the widget when the
  3793. menu is selected, and FILTER is a predicate which takes a `custom-group'
  3794. widget as an argument, and returns non-nil if ACTION is valid on that
  3795. widget. If FILTER is nil, ACTION is always valid.")
  3796. (defun custom-group-action (widget &optional event)
  3797. "Show the menu for `custom-group' WIDGET.
  3798. Optional EVENT is the location for the menu."
  3799. (if (eq (widget-get widget :custom-state) 'hidden)
  3800. (custom-toggle-hide widget)
  3801. (let* ((completion-ignore-case t)
  3802. (answer (widget-choose (concat "Operation on "
  3803. (custom-unlispify-tag-name
  3804. (widget-get widget :value)))
  3805. (custom-menu-filter custom-group-menu
  3806. widget)
  3807. event)))
  3808. (if answer
  3809. (funcall answer widget)))))
  3810. (defun custom-group-set (widget)
  3811. "Set changes in all modified group members."
  3812. (dolist (child (widget-get widget :children))
  3813. (when (eq (widget-get child :custom-state) 'modified)
  3814. (widget-apply child :custom-set))))
  3815. (defun custom-group-mark-to-save (widget)
  3816. "Mark all modified group members for saving."
  3817. (dolist (child (widget-get widget :children))
  3818. (when (memq (widget-get child :custom-state) '(modified set))
  3819. (widget-apply child :custom-mark-to-save))))
  3820. (defsubst custom-group-state-set-and-redraw (widget)
  3821. "Set state of group widget WIDGET and redraw with current settings."
  3822. (dolist (child (widget-get widget :children))
  3823. (when (memq (widget-get child :custom-state) '(modified set))
  3824. (widget-apply child :custom-state-set-and-redraw))))
  3825. (defun custom-group-save (widget)
  3826. "Save all modified group members."
  3827. (custom-group-mark-to-save widget)
  3828. (custom-save-all)
  3829. (custom-group-state-set-and-redraw widget))
  3830. (defun custom-group-reset-current (widget)
  3831. "Reset all modified group members."
  3832. (dolist (child (widget-get widget :children))
  3833. (when (eq (widget-get child :custom-state) 'modified)
  3834. (widget-apply child :custom-reset-current))))
  3835. (defun custom-group-reset-saved (widget)
  3836. "Reset all modified or set group members."
  3837. (dolist (child (widget-get widget :children))
  3838. (when (memq (widget-get child :custom-state) '(modified set))
  3839. (widget-apply child :custom-reset-saved))))
  3840. (defun custom-group-reset-standard (widget)
  3841. "Reset all modified, set, or saved group members."
  3842. (let ((custom-reset-standard-variables-list '(t))
  3843. (custom-reset-standard-faces-list '(t)))
  3844. (custom-group-mark-to-reset-standard widget)
  3845. (custom-reset-standard-save-and-update)))
  3846. (defun custom-group-mark-to-reset-standard (widget)
  3847. "Mark to reset all modified, set, or saved group members."
  3848. (dolist (child (widget-get widget :children))
  3849. (when (memq (widget-get child :custom-state)
  3850. '(modified set saved))
  3851. (widget-apply child :custom-mark-to-reset-standard))))
  3852. (defun custom-group-state-update (widget)
  3853. "Update magic."
  3854. (unless (eq (widget-get widget :custom-state) 'hidden)
  3855. (let* ((children (widget-get widget :children))
  3856. (states (mapcar (lambda (child)
  3857. (widget-get child :custom-state))
  3858. children))
  3859. (magics custom-magic-alist)
  3860. (found 'standard))
  3861. (while magics
  3862. (let ((magic (car (car magics))))
  3863. (if (and (not (eq magic 'hidden))
  3864. (memq magic states))
  3865. (setq found magic
  3866. magics nil)
  3867. (setq magics (cdr magics)))))
  3868. (widget-put widget :custom-state found)))
  3869. (custom-magic-reset widget))
  3870. ;;; Reading and writing the custom file.
  3871. ;;;###autoload
  3872. (defcustom custom-file nil
  3873. "File used for storing customization information.
  3874. The default is nil, which means to use your init file
  3875. as specified by `user-init-file'. If the value is not nil,
  3876. it should be an absolute file name.
  3877. You can set this option through Custom, if you carefully read the
  3878. last paragraph below. However, usually it is simpler to write
  3879. something like the following in your init file:
  3880. \(setq custom-file \"~/.emacs-custom.el\")
  3881. \(load custom-file)
  3882. Note that both lines are necessary: the first line tells Custom to
  3883. save all customizations in this file, but does not load it.
  3884. When you change this variable outside Custom, look in the
  3885. previous custom file (usually your init file) for the
  3886. forms `(custom-set-variables ...)' and `(custom-set-faces ...)',
  3887. and copy them (whichever ones you find) to the new custom file.
  3888. This will preserve your existing customizations.
  3889. If you save this option using Custom, Custom will write all
  3890. currently saved customizations, including the new one for this
  3891. option itself, into the file you specify, overwriting any
  3892. `custom-set-variables' and `custom-set-faces' forms already
  3893. present in that file. It will not delete any customizations from
  3894. the old custom file. You should do that manually if that is what you
  3895. want. You also have to put something like (load \"CUSTOM-FILE\")
  3896. in your init file, where CUSTOM-FILE is the actual name of the
  3897. file. Otherwise, Emacs will not load the file when it starts up,
  3898. and hence will not set `custom-file' to that file either."
  3899. :type '(choice (const :tag "Your Emacs init file" nil)
  3900. (file :format "%t:%v%d"
  3901. :doc
  3902. "Please read entire docstring below before setting \
  3903. this through Custom.
  3904. Click on \"More\" (or position point there and press RETURN)
  3905. if only the first line of the docstring is shown."))
  3906. :group 'customize)
  3907. (defun custom-file (&optional no-error)
  3908. "Return the file name for saving customizations."
  3909. (if (or (null user-init-file)
  3910. (and (null custom-file) init-file-had-error))
  3911. ;; Started with -q, i.e. the file containing Custom settings
  3912. ;; hasn't been read. Saving settings there won't make much
  3913. ;; sense.
  3914. (if no-error
  3915. nil
  3916. (user-error "Saving settings from \"emacs -q\" would overwrite existing customizations"))
  3917. (file-chase-links (or custom-file user-init-file))))
  3918. ;; If recentf-mode is non-nil, this is defined.
  3919. (declare-function recentf-expand-file-name "recentf" (name))
  3920. ;;;###autoload
  3921. (defun custom-save-all ()
  3922. "Save all customizations in `custom-file'."
  3923. (when (and (null custom-file) init-file-had-error)
  3924. (error "Cannot save customizations; init file was not fully loaded"))
  3925. (let* ((filename (custom-file))
  3926. (recentf-exclude
  3927. (if recentf-mode
  3928. (cons (concat "\\`"
  3929. (regexp-quote
  3930. (recentf-expand-file-name (custom-file)))
  3931. "\\'")
  3932. recentf-exclude)))
  3933. (old-buffer (find-buffer-visiting filename))
  3934. old-buffer-name)
  3935. (with-current-buffer (let ((find-file-visit-truename t))
  3936. (or old-buffer
  3937. (let ((delay-mode-hooks t))
  3938. (find-file-noselect filename))))
  3939. ;; We'll save using file-precious-flag, so avoid destroying
  3940. ;; symlinks. (If we're not already visiting the buffer, this is
  3941. ;; handled by find-file-visit-truename, above.)
  3942. (when old-buffer
  3943. (setq old-buffer-name (buffer-file-name))
  3944. (set-visited-file-name (file-chase-links filename)))
  3945. (unless (eq major-mode 'emacs-lisp-mode)
  3946. (delay-mode-hooks (emacs-lisp-mode)))
  3947. (let ((inhibit-read-only t)
  3948. (print-length nil)
  3949. (print-level nil))
  3950. (custom-save-variables)
  3951. (custom-save-faces))
  3952. (let ((file-precious-flag t))
  3953. (save-buffer))
  3954. (if old-buffer
  3955. (progn
  3956. (set-visited-file-name old-buffer-name)
  3957. (set-buffer-modified-p nil))
  3958. (kill-buffer (current-buffer))))))
  3959. ;;;###autoload
  3960. (defun customize-save-customized ()
  3961. "Save all user options which have been set in this session."
  3962. (interactive)
  3963. (mapatoms (lambda (symbol)
  3964. (let ((face (get symbol 'customized-face))
  3965. (value (get symbol 'customized-value))
  3966. (face-comment (get symbol 'customized-face-comment))
  3967. (variable-comment
  3968. (get symbol 'customized-variable-comment)))
  3969. (when face
  3970. (put symbol 'saved-face face)
  3971. (custom-push-theme 'theme-face symbol 'user 'set value)
  3972. (put symbol 'customized-face nil))
  3973. (when value
  3974. (put symbol 'saved-value value)
  3975. (custom-push-theme 'theme-value symbol 'user 'set value)
  3976. (put symbol 'customized-value nil))
  3977. (when variable-comment
  3978. (put symbol 'saved-variable-comment variable-comment)
  3979. (put symbol 'customized-variable-comment nil))
  3980. (when face-comment
  3981. (put symbol 'saved-face-comment face-comment)
  3982. (put symbol 'customized-face-comment nil)))))
  3983. ;; We really should update all custom buffers here.
  3984. (custom-save-all))
  3985. ;; Editing the custom file contents in a buffer.
  3986. (defun custom-save-delete (symbol)
  3987. "Delete all calls to SYMBOL from the contents of the current buffer.
  3988. Leave point at the old location of the first such call,
  3989. or (if there were none) at the end of the buffer.
  3990. This function does not save the buffer."
  3991. (goto-char (point-min))
  3992. ;; Skip all whitespace and comments.
  3993. (while (forward-comment 1))
  3994. (or (eobp)
  3995. (save-excursion (forward-sexp (buffer-size)))) ; Test for scan errors.
  3996. (let (first)
  3997. (catch 'found
  3998. (while t ;; We exit this loop only via throw.
  3999. ;; Skip all whitespace and comments.
  4000. (while (forward-comment 1))
  4001. (let ((start (point))
  4002. (sexp (condition-case nil
  4003. (read (current-buffer))
  4004. (end-of-file (throw 'found nil)))))
  4005. (when (and (listp sexp)
  4006. (eq (car sexp) symbol))
  4007. (delete-region start (point))
  4008. (unless first
  4009. (setq first (point)))))))
  4010. (if first
  4011. (goto-char first)
  4012. ;; Move in front of local variables, otherwise long Custom
  4013. ;; entries would make them ineffective.
  4014. (let ((pos (point-max))
  4015. (case-fold-search t))
  4016. (save-excursion
  4017. (goto-char (point-max))
  4018. (search-backward "\n\^L" (max (- (point-max) 3000) (point-min))
  4019. 'move)
  4020. (when (search-forward "Local Variables:" nil t)
  4021. (setq pos (line-beginning-position))))
  4022. (goto-char pos)))))
  4023. (defvar sort-fold-case) ; defined in sort.el
  4024. (defun custom-save-variables ()
  4025. "Save all customized variables in `custom-file'."
  4026. (save-excursion
  4027. (custom-save-delete 'custom-set-variables)
  4028. (let ((standard-output (current-buffer))
  4029. (saved-list (make-list 1 0))
  4030. sort-fold-case)
  4031. ;; First create a sorted list of saved variables.
  4032. (mapatoms
  4033. (lambda (symbol)
  4034. (if (and (get symbol 'saved-value)
  4035. ;; ignore theme values
  4036. (or (null (get symbol 'theme-value))
  4037. (eq 'user (caar (get symbol 'theme-value)))))
  4038. (nconc saved-list (list symbol)))))
  4039. (setq saved-list (sort (cdr saved-list) 'string<))
  4040. (unless (bolp)
  4041. (princ "\n"))
  4042. (princ "(custom-set-variables
  4043. ;; custom-set-variables was added by Custom.
  4044. ;; If you edit it by hand, you could mess it up, so be careful.
  4045. ;; Your init file should contain only one such instance.
  4046. ;; If there is more than one, they won't work right.\n")
  4047. (dolist (symbol saved-list)
  4048. (let ((spec (car-safe (get symbol 'theme-value)))
  4049. (value (get symbol 'saved-value))
  4050. (requests (get symbol 'custom-requests))
  4051. (now (and (not (custom-variable-p symbol))
  4052. (or (boundp symbol)
  4053. (eq (get symbol 'force-value)
  4054. 'rogue))))
  4055. (comment (get symbol 'saved-variable-comment)))
  4056. ;; Check REQUESTS for validity.
  4057. (dolist (request requests)
  4058. (when (and (symbolp request) (not (featurep request)))
  4059. (message "Unknown requested feature: %s" request)
  4060. (setq requests (delq request requests))))
  4061. ;; Is there anything customized about this variable?
  4062. (when (or (and spec (eq (car spec) 'user))
  4063. comment
  4064. (and (null spec) (get symbol 'saved-value)))
  4065. ;; Output an element for this variable.
  4066. ;; It has the form (SYMBOL VALUE-FORM NOW REQUESTS COMMENT).
  4067. ;; SYMBOL is the variable name.
  4068. ;; VALUE-FORM is an expression to return the customized value.
  4069. ;; NOW if non-nil means always set the variable immediately
  4070. ;; when the customizations are reloaded. This is used
  4071. ;; for rogue variables
  4072. ;; REQUESTS is a list of packages to load before setting the
  4073. ;; variable. Each element of it will be passed to `require'.
  4074. ;; COMMENT is whatever comment the user has specified
  4075. ;; with the customize facility.
  4076. (unless (bolp)
  4077. (princ "\n"))
  4078. (princ " '(")
  4079. (prin1 symbol)
  4080. (princ " ")
  4081. (let ((val (prin1-to-string (car value))))
  4082. (if (< (length val) 60)
  4083. (insert val)
  4084. (newline-and-indent)
  4085. (let ((beginning-of-val (point)))
  4086. (insert val)
  4087. (save-excursion
  4088. (goto-char beginning-of-val)
  4089. (indent-pp-sexp 1)))))
  4090. (when (or now requests comment)
  4091. (princ " ")
  4092. (prin1 now)
  4093. (when (or requests comment)
  4094. (princ " ")
  4095. (prin1 requests)
  4096. (when comment
  4097. (princ " ")
  4098. (prin1 comment))))
  4099. (princ ")"))))
  4100. (if (bolp)
  4101. (princ " "))
  4102. (princ ")")
  4103. (unless (looking-at-p "\n")
  4104. (princ "\n")))))
  4105. (defun custom-save-faces ()
  4106. "Save all customized faces in `custom-file'."
  4107. (save-excursion
  4108. (custom-save-delete 'custom-reset-faces)
  4109. (custom-save-delete 'custom-set-faces)
  4110. (let ((standard-output (current-buffer))
  4111. (saved-list (make-list 1 0))
  4112. sort-fold-case)
  4113. ;; First create a sorted list of saved faces.
  4114. (mapatoms
  4115. (lambda (symbol)
  4116. (if (and (get symbol 'saved-face)
  4117. (eq 'user (car (car-safe (get symbol 'theme-face)))))
  4118. (nconc saved-list (list symbol)))))
  4119. (setq saved-list (sort (cdr saved-list) 'string<))
  4120. ;; The default face must be first, since it affects the others.
  4121. (if (memq 'default saved-list)
  4122. (setq saved-list (cons 'default (delq 'default saved-list))))
  4123. (unless (bolp)
  4124. (princ "\n"))
  4125. (princ "(custom-set-faces
  4126. ;; custom-set-faces was added by Custom.
  4127. ;; If you edit it by hand, you could mess it up, so be careful.
  4128. ;; Your init file should contain only one such instance.
  4129. ;; If there is more than one, they won't work right.\n")
  4130. (dolist (symbol saved-list)
  4131. (let ((spec (car-safe (get symbol 'theme-face)))
  4132. (value (get symbol 'saved-face))
  4133. (now (not (or (get symbol 'face-defface-spec)
  4134. (and (not (custom-facep symbol))
  4135. (not (get symbol 'force-face))))))
  4136. (comment (get symbol 'saved-face-comment)))
  4137. (when (or (and spec (eq (nth 0 spec) 'user))
  4138. comment
  4139. (and (null spec) (get symbol 'saved-face)))
  4140. ;; Don't print default face here.
  4141. (unless (bolp)
  4142. (princ "\n"))
  4143. (princ " '(")
  4144. (prin1 symbol)
  4145. (princ " ")
  4146. (prin1 value)
  4147. (when (or now comment)
  4148. (princ " ")
  4149. (prin1 now)
  4150. (when comment
  4151. (princ " ")
  4152. (prin1 comment)))
  4153. (princ ")"))))
  4154. (if (bolp)
  4155. (princ " "))
  4156. (princ ")")
  4157. (unless (looking-at-p "\n")
  4158. (princ "\n")))))
  4159. ;;; The Customize Menu.
  4160. ;;; Menu support
  4161. (defcustom custom-menu-nesting 2
  4162. "Maximum nesting in custom menus."
  4163. :type 'integer
  4164. :group 'custom-menu)
  4165. (defun custom-face-menu-create (_widget symbol)
  4166. "Ignoring WIDGET, create a menu entry for customization face SYMBOL."
  4167. (vector (custom-unlispify-menu-entry symbol)
  4168. `(customize-face ',symbol)
  4169. t))
  4170. (defun custom-variable-menu-create (_widget symbol)
  4171. "Ignoring WIDGET, create a menu entry for customization variable SYMBOL."
  4172. (let ((type (get symbol 'custom-type)))
  4173. (unless (listp type)
  4174. (setq type (list type)))
  4175. (if (and type (widget-get type :custom-menu))
  4176. (widget-apply type :custom-menu symbol)
  4177. (vector (custom-unlispify-menu-entry symbol)
  4178. `(customize-variable ',symbol)
  4179. t))))
  4180. ;; Add checkboxes to boolean variable entries.
  4181. (widget-put (get 'boolean 'widget-type)
  4182. :custom-menu (lambda (_widget symbol)
  4183. (vector (custom-unlispify-menu-entry symbol)
  4184. `(customize-variable ',symbol)
  4185. ':style 'toggle
  4186. ':selected symbol)))
  4187. (defun custom-group-menu-create (_widget symbol)
  4188. "Ignoring WIDGET, create a menu entry for customization group SYMBOL."
  4189. `( ,(custom-unlispify-menu-entry symbol t)
  4190. :filter (lambda (&rest junk)
  4191. (let* ((menu (custom-menu-create ',symbol)))
  4192. (if (consp menu) (cdr menu) menu)))))
  4193. ;;;###autoload
  4194. (defun custom-menu-create (symbol)
  4195. "Create menu for customization group SYMBOL.
  4196. The menu is in a format applicable to `easy-menu-define'."
  4197. (let* ((deactivate-mark nil)
  4198. (item (vector (custom-unlispify-menu-entry symbol)
  4199. `(customize-group ',symbol)
  4200. t)))
  4201. (if (and (or (not (boundp 'custom-menu-nesting))
  4202. (>= custom-menu-nesting 0))
  4203. (progn
  4204. (custom-load-symbol symbol)
  4205. (< (length (get symbol 'custom-group)) widget-menu-max-size)))
  4206. (let ((custom-prefix-list (custom-prefix-add symbol
  4207. custom-prefix-list))
  4208. (members (custom-sort-items (get symbol 'custom-group)
  4209. custom-menu-sort-alphabetically
  4210. custom-menu-order-groups)))
  4211. `(,(custom-unlispify-menu-entry symbol t)
  4212. ,item
  4213. "--"
  4214. ,@(mapcar (lambda (entry)
  4215. (widget-apply (if (listp (nth 1 entry))
  4216. (nth 1 entry)
  4217. (list (nth 1 entry)))
  4218. :custom-menu (nth 0 entry)))
  4219. members)))
  4220. item)))
  4221. ;;;###autoload
  4222. (defun customize-menu-create (symbol &optional name)
  4223. "Return a customize menu for customization group SYMBOL.
  4224. If optional NAME is given, use that as the name of the menu.
  4225. Otherwise the menu will be named `Customize'.
  4226. The format is suitable for use with `easy-menu-define'."
  4227. (unless name
  4228. (setq name "Customize"))
  4229. `(,name
  4230. :filter (lambda (&rest junk)
  4231. (let ((menu (custom-menu-create ',symbol)))
  4232. (if (consp menu) (cdr menu) menu)))))
  4233. ;;; Toolbar and menubar support
  4234. (easy-menu-define
  4235. Custom-mode-menu (list custom-mode-map custom-field-keymap)
  4236. "Menu used in customization buffers."
  4237. (nconc (list "Custom"
  4238. (customize-menu-create 'customize))
  4239. (mapcar (lambda (arg)
  4240. (let ((tag (nth 0 arg))
  4241. (command (nth 1 arg))
  4242. (active (nth 2 arg))
  4243. (help (nth 3 arg)))
  4244. (vector tag command :active (eval active) :help help)))
  4245. custom-commands)))
  4246. (defvar tool-bar-map)
  4247. ;;; `custom-tool-bar-map' used to be set up here. This will fail to
  4248. ;;; DTRT when `display-graphic-p' returns nil during compilation. Hence
  4249. ;;; we set this up lazily in `Custom-mode'.
  4250. (defvar custom-tool-bar-map nil
  4251. "Keymap for toolbar in Custom mode.")
  4252. ;;; The Custom Mode.
  4253. (defun Custom-no-edit (_pos &optional _event)
  4254. "Invoke button at POS, or refuse to allow editing of Custom buffer."
  4255. (interactive "@d")
  4256. (error "You can't edit this part of the Custom buffer"))
  4257. (defun Custom-newline (pos &optional event)
  4258. "Invoke button at POS, or refuse to allow editing of Custom buffer."
  4259. (interactive "@d")
  4260. (let ((button (get-char-property pos 'button)))
  4261. ;; If there is no button at point, then use the one at the start
  4262. ;; of the line, if it is a custom-group-link (bug#2298).
  4263. (or button
  4264. (if (setq button (get-char-property (line-beginning-position) 'button))
  4265. (or (eq (widget-type button) 'custom-group-link)
  4266. (setq button nil))))
  4267. (if button
  4268. (widget-apply-action button event)
  4269. (error "You can't edit this part of the Custom buffer"))))
  4270. (defun Custom-goto-parent ()
  4271. "Go to the parent group listed at the top of this buffer.
  4272. If several parents are listed, go to the first of them."
  4273. (interactive)
  4274. (save-excursion
  4275. (goto-char (point-min))
  4276. (if (search-forward "\nParent groups: " nil t)
  4277. (let* ((button (get-char-property (point) 'button))
  4278. (parent (downcase (widget-get button :tag))))
  4279. (customize-group parent)))))
  4280. (defcustom Custom-mode-hook nil
  4281. "Hook called when entering Custom mode."
  4282. :type 'hook
  4283. :group 'custom-buffer)
  4284. (defun custom-state-buffer-message (widget)
  4285. (if (eq (widget-get (widget-get widget :parent) :custom-state) 'modified)
  4286. (message "To install your edits, invoke [State] and choose the Set operation")))
  4287. (defun custom--initialize-widget-variables ()
  4288. (setq-local widget-documentation-face 'custom-documentation)
  4289. (setq-local widget-button-face custom-button)
  4290. (setq-local widget-button-pressed-face custom-button-pressed)
  4291. (setq-local widget-mouse-face custom-button-mouse)
  4292. ;; We need this because of the "More" button on docstrings.
  4293. ;; Otherwise clicking on "More" can push point offscreen, which
  4294. ;; causes the window to recenter on point, which pushes the
  4295. ;; newly-revealed docstring offscreen; which is annoying. -- cyd.
  4296. (setq-local widget-button-click-moves-point t)
  4297. ;; When possible, use relief for buttons, not bracketing. This test
  4298. ;; may not be optimal.
  4299. (when custom-raised-buttons
  4300. (setq-local widget-push-button-prefix "")
  4301. (setq-local widget-push-button-suffix "")
  4302. (setq-local widget-link-prefix "")
  4303. (setq-local widget-link-suffix ""))
  4304. (setq show-trailing-whitespace nil))
  4305. (define-obsolete-variable-alias 'custom-mode-hook 'Custom-mode-hook "23.1")
  4306. (define-derived-mode Custom-mode nil "Custom"
  4307. "Major mode for editing customization buffers.
  4308. The following commands are available:
  4309. \\<widget-keymap>\
  4310. Move to next button, link or editable field. \\[widget-forward]
  4311. Move to previous button, link or editable field. \\[widget-backward]
  4312. \\<custom-field-keymap>\
  4313. Complete content of editable text field. \\[widget-complete]
  4314. \\<custom-mode-map>\
  4315. Invoke button under the mouse pointer. \\[widget-button-click]
  4316. Invoke button under point. \\[widget-button-press]
  4317. Set all options from current text. \\[Custom-set]
  4318. Make values in current text permanent. \\[Custom-save]
  4319. Make text match actual option values. \\[Custom-reset-current]
  4320. Reset options to permanent settings. \\[Custom-reset-saved]
  4321. Erase customizations; set options
  4322. and buffer text to the standard values. \\[Custom-reset-standard]
  4323. Entry to this mode calls the value of `Custom-mode-hook'
  4324. if that value is non-nil."
  4325. (use-local-map custom-mode-map)
  4326. (easy-menu-add Custom-mode-menu)
  4327. (setq-local tool-bar-map
  4328. (or custom-tool-bar-map
  4329. ;; Set up `custom-tool-bar-map'.
  4330. (let ((map (make-sparse-keymap)))
  4331. (mapc
  4332. (lambda (arg)
  4333. (tool-bar-local-item-from-menu
  4334. (nth 1 arg) (nth 4 arg) map custom-mode-map
  4335. :label (nth 5 arg)))
  4336. custom-commands)
  4337. (setq custom-tool-bar-map map))))
  4338. (make-local-variable 'custom-options)
  4339. (make-local-variable 'custom-local-buffer)
  4340. (custom--initialize-widget-variables)
  4341. (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t))
  4342. (put 'Custom-mode 'mode-class 'special)
  4343. (define-obsolete-function-alias 'custom-mode 'Custom-mode "23.1")
  4344. (add-to-list 'debug-ignored-errors "^Invalid face:? ")
  4345. ;;; The End.
  4346. (provide 'cus-edit)
  4347. ;;; cus-edit.el ends here