<!DOCTYPE Rambledocs SYSTEM "~/dtd/rambledocs-3.dtd" >

<Rambledocs>
  <General-comments>
    <Node>
      <Text-Node Title="Psgml-using functions">
	For most of these, we should assure that we are in an xml
	buffer, using the appropriate doc dtd.  

	As another safeguard, make separate minor modes for both elisp
	and psgml.  The appropriate minor mode would be turned on when
	create a new docfile, and assured on when we go to the docfile
	at all.
	
	(This is an example of the sort of digression that should have
	a place elsewhere in the docs)  (Which I later added)

      </Text-Node>
    </Node>
    <Node Title="imenu or tags?">
      <Text-Node>
	Here's my dilemma: I could continue using the imenu approach
	or I could work with tags/etags.  I've already done the imenu
	stuff, but I'm not so locked into it, and tags is a more
	standard tool.  It also automatically supports multi-file
	stuff.
      </Text-Node>
      
      <Text-Node Title="To use tags">
	To use tags, I'd still have to force rescans in much the same
	way, I could pipe output into a buffer copy of the TAGS file
	with something like "etags $1 --output=-" to reduce disk
	hitting.
	
	And I'd use one or more of the find-tag functions, which is
	easy enuff to call.

	I'd have to temporarily set the current tags table.  That
	looked tricky, but setting the current tags table looks to be
	the province of (visit-tags-table-buffer "$Tag_file_name" )

	So basically it wouldn't be hard as hard as I thaut to switch
	to tags, and it may well support things like multiple files
	that imenu couldn't.

      </Text-Node>
    </Node>
    <Node Title="On the general commentary">
      <Text-Node>
	One thing that's bugging me is that the outline-like general
	commentary may be imposing too much structure on the user.

	It isn't a simple bag of named ideas like the list of
	functions, it's trying to be a fully-structured outline, and
	that means that it wants prior design effort, which is what
	I'm trying to avoid requiring.

	One approach would be to treat it like a bag too, allowing the
	functions' "Ramble" sections or some optional subcomponent
	thereof to "name" the relevant section and go to it, much the
	way functions and docs interpoint.  This has the disadvantage
	of adding extra structure ot the functions, but the elements
	involved can be optional.

      </Text-Node>
    </Node>
    <Node Title="On the dtd">
      <Text-Node Title="The embedded outline">

	"Node" and "Text-node" are basically an ordinary outline
	expressed in XML.  That's a fairly simply structure,

      </Text-Node>
      <Text-Node Title="The Component element">

	The "Component" element will later become more complex,
	splittable into problems, with associated approaches etc.  All
	of its subelements and/or sibling elements should be optional

	It may need renaming, as it's not always a function that's
	it's referring to.

      </Text-Node>
      <Text-Node Title="The group element">	

	The group element groups together API components or groups of
	them.

	Perhaps group start with comments (The general comments?) and
	should only allow groups or functions, not both.
	Unfortunately, psgml doesn't enforce that, so there's a risk
	that it could get messed up.

      </Text-Node>
      <Text-Node>
	If the top-level docs section includes general-comments, the
	single group element included in it shouldn't also have
	comments.  So the top-level thing should have the same
	structure as group, including the possibility of multiple
	functions all by itself, so it has to be recognized if nothing
	else is valid to insert in.
      </Text-Node>
      <Text-Node> 

	We need a unique place to automatically insert new functions,
	and with this "tree" there's no such unique place.  Perhaps a
	group could be marked "active" to receive 'em?  Eh, that's
	quite ambitious.  Too ambitious for now.
	
	ISTM it's better to simply have one place for all the
	functions.  We can get more sophisticated later if that's
	warranted.  So all the group stuff doesn't belong here yet.
      </Text-Node>

    </Node>
    <Node Title="Still to do">
      <Text-Node>

	More fussing with the dtd.  Give it another section for
	general comments?  Done.
      </Text-Node>
      <Text-Node> 

	I'd like to handle other things besides functions.  At least
	types and variables.  

	In fact, that falls out naturally from within the elisp, but
	doesn't go naturally the other way, because imenu doesn't
	support that.
      </Text-Node>
      <Text-Node>	

	Some name-changes in the dtd may be appropriate.  Use a
	different name than function and make an attribute that can be
	function, variable, type, or other (Syntax-unknown) .
      </Text-Node>
      <Text-Node>	

	Still need to force rescans.  Somehow, can we know what time
	the buffer was last modified?  Yup, with
	(buffer-modified-tick).  Done.
      </Text-Node>
      <Text-Node>	
	Need to cope if imenu returns a long list that gets split.
	
      </Text-Node>
      <Text-Node Title="Name conventions">	
	
	Is "docwork" a good name?  Rambledocs?  I should change the
	dtd doc name to something better than "Docs"
	

      </Text-Node>
    </Node>
  </General-comments>

  <Group Name="Functions to get the associated filename">
    <General-comments>
    </General-comments>
    <Component Name="rmb-get-docfile-name">
    
      Called while in an elisp file, or passing it as the buffer.
      This should not be called on a buffer that's not source code,
      but controlling that is tuff.
    
    </Component>

    <Component Name="rmb-get-srcfile-name">
    
      This basically undoes the filename transformation made by
      rmb-get-docfile-name.

      It is likely we'll want some regexp-driven variability for this.

      Note that the regexp needs "\\" to generate a regexp magic
      backslash and "\\\\" to generate a normal, non-magic backslash.
 
      (Put this in a more-general considerations section)
      For stuff that starts in docfile, we can check that it's a psgml
      file with the appropriate doctype and abort if it's not. 
    
    </Component>
  </Group>
  <Group Name="Go to the associated file">
    <General-comments>
    </General-comments>
    <Component Name="rmb-docfile-extension">
    </Component>
    <Component Name="rmb-find-docfile">
    
      rmb-find-docfile and rmb-find-docfile-other-window only set up
      the buffer as a docfile if the file is new.  It's possible they
      should always make sure it's set up, which would mean calling
      rmb-set-up-doc-buffer all the time instead of only calling it
      in find-file-not-found-hooks, and would not require
      rmb-fill-docfile to specifically call rmb-set-up-doc-buffer.

    
    </Component>
    <Component Name="rmb-find-docfile-other-window">
    </Component>
    <Component Name="rmb-find-srcfile">
    </Component>
    <Component Name="rmb-find-srcfile-other-window">
    </Component>
  </Group>
  
  <Component Name="rmb-get-function-name">
    
      For now, we search for defun.  defstruct, defsubst, defmacro
      will be later.  

      In fact, just have a list of such keywords.

      But first, look up how this is already done and see if there's
      any existing help.

      This does find defuns, but wierdly.  I'll live with it.

      We may test the atomicity of ob later, in case its

      This invites all sorts of data-driven formatting.  A tempting
      approach is to interpret a string like "(defun NAME" to give the
      appropriate search instructions.  

      In any case, it's clear that many variations will be desirable.

    
  </Component>
  <Component Name="rmb-make-new-doc-entry">
    
      We may want more parameters besides name.  This depends on the
      DTD, but type would not be unreasonable.

      This will have to futz around with the psgml inner workings.
      Look at psgml-api in *info*.  

      Element names are found with (sgml-element-gi ELEMENT),
      attributes with (sgml-element-attval ELEMENT ATTRIBUTE). Iterate
      with (sgml-element-next) from (sgml-top-element)

      For this and other functions that start in the doc buffer, check
      that (sgml-dtd-doctype (sgml-pstate-dtd
      sgml-buffer-parse-state)) is the rambledocs dtd, which means first
      assuring that we've parsed, with (sgml-need-dtd).

      I've had to borrow some psgml functions and rewrite them to get
      more control over how an element gets inserted.

      This function is now returning a position, but I want it to
      return the element it just made.

    
  </Component>
  
  <Component Name="rmb-insert-doc-dtd">
    

      This is basically like C-c C-u C-d, but it inserts specifically
      the doc dtd.  That's sgml-custom-dtd in `psgml-edit', which uses
      sgml-doctype-insert to do the work.
      
      In fact, we'll call: (sgml-doctype-insert doctype vars).  Doctype
      looks like it will be a string, eventually made from user
      variables.  vars I'm not so sure about.

      This should be called if the found doc-file is new or blank.
      For this function alone, we don't want to test whether we're in
      "a real docfile buffer" -- we're not.
    
  </Component>
  <Component Name="rmb-find-doc-element">
    
    This function is very fragile wrt the exact dtd rite now.

    It is now changed to search recursively, for the new dtd that uses
    grouping. 

  </Component>
  <Component Name="rmb-go-to-match-in-doc">
    
      This should only be called in the source buffer, but will put
      the user into the doc file buffer.

    
  </Component>
  <Component Name="rmb-sgml-insert-element">
    
      Of several functions borrowed from psgml, this is the most
      changed.  I'd've liked to do more but couldn't spare the time.

      I rewrote it to accept attribute lists as an argument, rather
      than neccessarily requiring user interaction.  They are alists
      of ("Att-name" . "Att-value-string"), the same as what
      sgml-new-attribute-list-function returns.

      I would have liked to have extended the controller format, so
      that it could a) choose content elements where the choice was
      ambiguous, and b) manage recursion, so that sub-elements'
      attributes could also be controlled.  I didn't need any of that
      for rambledocs, but it'd be nice.

      I'm not comfortable with neccessarily using the value of (point)
      to figure out ELEMENT, but I don't see an easy alternative.

      I've commented the function to make it much clearer, and
      re-arranged it in some trivial ways.
      
    
  </Component>
  <Component Name="rmb-sgml-find-insert-position">
    
      This is a new function excerpted from psgml.

      I fixed the loop so it no longer makes assignments in tests and
      I commented it.

    
  </Component>
  <Component Name="rmb-sgml-add-element-to-element">
    
      Borrowed from psgml-edit and forced to call
      rmb-sgml-insert-element instead of sgml-insert-element

      Another change, cosmetic only, was to excerpt
      rmb-sgml-find-insert-position from here.
      this.
    
  </Component>
  <Component Name="rmb-go-to-doc-component">
    
      This should only be called within a docfile.  It's basically a
      lagniappe for user interaction, not an important part of
      rambledocs.  
    
  </Component>
  <Component Name="rmb-doc-get-component-name">
    
      Seemed easy.  One problem is that the point may be in a
      sub-element, and thus not have direct access to the function
      name.

      So we sometimes have to climb back up the tree, which shouldn't
      be hard.

      I've changed this to extract two looping control functions,
      rmb-sgml-get-enclosing-el and
      rmb-sgml-get-enclosing-element-by-name. 
    
  </Component>
  <Component Name="rmb-go-to-src-element">
    
      function to go to the appropriate place in the sourcefile.
      imenu may be a lot of help in finding all the defuns, and
      perhaps we could share code with it.

      In fact, imenu--make-index-alist will do almost all the work for
      us.  

      There is some possibility of getting out of sync with the file.
      We could force a rescan if the source buffer has changed, since
      imenu doesn't seem to do that.

      We want to skip stuff imenu returns that's not relevant, such as
      *Rescan*, and we want to treat "Variables" and "Types" smarter.

      For now, we assume we're only looking at functions and we just
      ignore the "Variables" and "Types" list.  Once we find a match,
      we go to the appropriate marker.

      OK, this works now but it's sloppy: We have no way of finding
      variables and types, we don't force a rescan, and if the name
      matches "*Rescan*", "Variables", or "Types" we're wrecked.

      OK, I fixed that so that targets with those names abort.  It
      still doesn't handle variables and types intelligently, tho.  We
      should recognize that a name is a variable or type, not a
      function, and use the appropriate alist, which isn't hard to
      find.  Alternatively, we could scan all such lists.

    
  </Component>
  <Component Name="rmb-in-rambledocs-buffer-p">
    
      I have added this function as a guard for everything that must
      only be called in a rambledocs buffer, or must never be.

      Perhaps the keyword "Rambledocs" should be excerpted to a user
      variable. [Done]

      If there is no dtd, this function crashes and dies.
      
      Fixed by enclosing (sgml-need-dtd) in error-trapping, so that if
      it fails we just return nil instead of die. 
      
    
  </Component>
  <Component Name="rmb-go-to-match-in-src">
    
      We don't support creating elisp defuns etc from docs, because
      that's too complicated and too sensitive.
    
  </Component>
  
  
  
  <Component Name="rmb-src-get-function-name">
    
    
  </Component>
  <Component Name="rmb-force-go-to-doc-name">
    
    
  </Component>
  <Component Name="rmb-fill-docfile">
    
      Worked great!  It just saved me from manually creating half a
      dozen entries.

      Which, come to think of it, would have happened mostly
      automatically anyways; Oh, well.

      This has another problem:  It doesn't insert the top-level
      element, so the newly-inserted elements have nowhere to go. [Fixed]

      Nah, inserting the dtd does NOT happen automatically.
      rmb-fill-docfile should be called whenever we open the doc file
      and find it didn't exist.  Is there some way to know that?

      When we call find-file[-other-window], find-file-not-found-hooks
      is called when it's a new file.  If we temporarily add a hook to
      that, we can put the dtd etc into the buffer.  Return non-nil to
      stop any other hooks from operating at this time.  

      (let* 
      ((find-file-not-found-hooks find-file-not-found-hooks))

      (add-hook 
      'find-file-not-found-hooks
      ( function
      ( lambda ()
	(insert "Here I come to save the day!\n"
	  (format "find-file-not-found-hooks == %S\n" 
	    find-file-not-found-hooks))
	
      t)))
  
      (find-file "Ooozamug"))


      We auto encap some other functionality with rmb-insert-doc-dtd,
      but don't insert all the functions.  Just the functionality that
      does (rmb-sgml-insert-element ... ).  End by returning non-nil,
      which means the other stuff doesn't get called, we've handled
      it.
      
      
    
  </Component>
  <Component Name="rmb-doc-dtd-local-variables">
    
      This punts on exactly how to set the list.  It could use :format
      and :doc to document them better.

      ISTRT psgml provides something like that to set local variables
      for being inserted into a buffer, perhaps I can copy that.

    
  </Component>
  <Group Name="Modes">
    <General-comments>
    </General-comments>
    <Component Name="rmb-doc-mode">
    
      A minor mode to control commands in rambledocs doc buffer.

      While writing this, it occurs to me that a small improvement to
      easy-mmode-define-minor-mode would be to define a key-definition
      prefix and automatically add it, with something like: (mapcar
      #'(cons (concat "\C-c;" (car cell)) (cdr cell)) that-alist )

      Another improvement would be to make sure the mode variable
      actually ends in mode before that's stripped off in some places,
      added in others.

    
  </Component>
  <Component Name="rmb-src-mode">
    
      Similarly, a minor mode for source buffer.
    
  </Component>
  </Group>
  <Component Name="rmb-imenu-force-rescan">
    
      Would be nice if this were a part of imenu's API instead of just
      something hidden in it.
    
  </Component>
  <Component Name="rmb-imenu--make-index-alist">
    
      This merely forces a rescan when needed, IE when
      (buffer-modified-tick) has changed.

      I want to change this so that it doesn't store those messages in
      the message recall buffer.
    
  </Component>
  
  <Component Name="rmb-doc-get-backref-component-name">
    
      This finds the Component enclosing the point and finds its
      backref. 

      Parse to find a backref element, if any.  (Done)

      If it has multiple backrefs, let the user pick.  (Issue) This
      depends on exactly how we represent backrefs.

      (Chosen) A list within backrefs?  (Formal) EMPTY content, name
      attribute.  Easy to make a completion list, simply loop thru the
      children and make a car cell of (car gi c), using
      completing-read, or better, finally make a variant
      tehom-completing-read-assoc that directly gives the data by
      assoc, put it in a new tehom source file.  (Done) (Done)

      A list of attributes within the backrefs element?  (Not sure
      it's even possible)

      Many backrefs directly within the Component itself?  (Less
      formal, harder to make a completion list)

      If no backrefs are found, ( error "%s has no backward references"
      (sgml-element-attval el "Name" ))
      
      Some iterators for psgml would be nice: do-children (like
      dolist), map-children (like mapcar)
    
  </Component>
  <Component Name="rmb-set-up-doc-buffer">
    No commentary here.
    
  </Component>
</Rambledocs>
