Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pasdoc (and Help Insight) comments support #8

Closed
pascalecu opened this issue Sep 26, 2024 · 1 comment
Closed

Pasdoc (and Help Insight) comments support #8

pascalecu opened this issue Sep 26, 2024 · 1 comment

Comments

@pascalecu
Copy link

Hi! I wanted to come by and say I really like your work.

With that being said, I noticed this doesn't have support for Pasdoc, which is:

a documentation tool for the Object Pascal code (as implemented by FreePascal and Delphi). Documentation is generated from comments found in the source code and from external files.

It is used by various projects such as Castle Game Engine (this tool was made by its creator, Michalis Kamburelis), Synapse, SynEdit, PasDoc itself of course, Allegro.pas, Brook and FBLib.

Specifically, it supports two syntaxes: the Help Insight format used most commonly on Delphi (which is just XMLDoc):

/// <summary>parses the commandline</summary>
/// <param name="CmdLine"> is a string giving the commandline.
/// NOTE: Do not pass System.CmdLine since it contains the
/// program's name as the first "parameter".
/// If you want to parse the commandline as passed by
/// windows, call the overloaded Parse method without
/// parameters. It handles this.</param>
procedure Parse(const _CmdLine: string);

and a JavaDoc-esque format, which is the main way:

{ In this game, there are various types of items:
  @definitionList(
    @itemLabel(Usable, always)
    @item(Typical items that are used. Scrolls, potions, books etc.
      You should override this method to define what
      happens when player uses this item.)

    @itemLabel(Usable, but only when equipped)
    @item(Items that can be used but must be equipped first. E.g.
      magic staffs. You should override this method and check for
      @link(IsEquipped) inside.)

    @itemLabel(Not usable)
    @item(Items that can't be used.
      Don't override this method, default implementation in this
      class will raise an exception.)
  )
}
procedure Use;
{ @abstract(Test of highlighting in @@longCode some things.)

  See
  [https://sourceforge.net/tracker/?func=detail&atid=354213&aid=1422011&group_id=4213]

  @longCode(#
  TOptions = class(TForm)
  private
    procedure WMSysCmd(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
  ...
  end;
  #)

  See https://github.com/pasdoc/pasdoc/issues/123 :

  @longcode(#
  Somethins.Name:=1;
  I:=123;
  R:=0.001;
  R:=1E10;
  R:=R*0.99 - 9E-4;
  #)
}
    { Right and top coordinates of the rectangle.
      @code(Right) is simply the @code(Left + Width),
      @code(Top) is simply the @code(Bottom + Height).

      If you use this for drawing, note that the pixel
      with coordinates @code((Right, Top)) is actually *outside*
      of the rectangle (by 1 pixel). That's because the rectangle starts at
      pixel @code((Left, Bottom)) and spans the @code((Width, Height)) pixels.
      @groupBegin }
    property Right: Integer read GetRight;
    property Top: Integer read GetTop;
    { @groupEnd }

    { Return rectangle with given width and height centered
      in the middle of this rectangle. The given W, H may be smaller or larger
      than this rectangle sizes. }
    function CenterInside(const W, H: Cardinal): TRectangle;

    { Grow (when Delta > 0) or shrink (when Delta < 0)
      the rectangle, returning new value.
      This adds a margin of Delta pixels around all sides of the rectangle,
      so in total width grows by 2 * Delta, and the same for height.
      In case of shrinking, we protect from shrinking too much:
      the resulting width or height is set to zero (which makes a valid
      and empty rectangle) if shrinking too much. }
    function Grow(const Delta: Integer): TRectangle; overload;
    function Grow(const DeltaX, DeltaY: Integer): TRectangle; overload;

    { Returns the rectangle with a number of pixels from given
      side removed. Returns an empty rectangle if you try to remove too much.
      @groupBegin }
    function RemoveLeft(W: Cardinal): TRectangle;
    function RemoveBottom(H: Cardinal): TRectangle;
    function RemoveRight(W: Cardinal): TRectangle;
    function RemoveTop(H: Cardinal): TRectangle;
    { @groupEnd }

    { Returns the rectangle with a number of pixels on given
      side added.
      @groupBegin }
    function GrowLeft(const W: Cardinal): TRectangle;
    function GrowBottom(const H: Cardinal): TRectangle;
    function GrowRight(const W: Cardinal): TRectangle;
    function GrowTop(const H: Cardinal): TRectangle;
    { @groupEnd }

    { Scale rectangle position and size around the (0,0) point.

      Since the scaling is independent in each axis,
      this handles "carefully" a half-empty rectangles
      (when one size is <= 0, but other is > 0).
      It scales correctly the positive dimension
      (not just returns @link(Empty) constant),
      leaving the other dimension (it's position and size) untouched.

      These details matter, e.g. when you set @link(TCastleUserInterface.Width), but not
      @link(TCastleUserInterface.Height),
      and then you expect the @link(TCastleUserInterface.EffectiveWidth) to work.
    }
    function ScaleAround0(const Factor: Single): TRectangle;

    { Common part of the two rectangles. }
    class operator {$ifdef FPC}*{$else}Multiply{$endif} (const R1, R2: TRectangle): TRectangle;

    function Equals(const R: TRectangle): Boolean;
  end;

(the last code snippet is taken from Castle Game Engine's source code, it is partially reproduced for size, to get the point across).

The parens are optional, but help with grouping.

Thus, I imagine support for these documentation languages could be achieved using injected languages. Help Insight comments always begin with 3 slashes, and that's where one could simply inject the XML parser. I am not that sure about the JavaDoc-esque comments (and especially @longcode, which would necessitate injecting the Pascal TS grammar into a comment). How would you approach this? Because I am not sure if this is something that downstream should support (i.e. nvim-treesitter, *-ts-mode on Emacs etc.) or if this requires upstream support.

@Isopod
Copy link
Owner

Isopod commented Dec 12, 2024

Hi, sorry I didn't respond to this, yet.

You've probably figured it out yourself by now, but in Tree-Sitter stuff like this is done using language injections, for example in nvim-treesitter this is handled by injecting the comment pseudo-language here. You would have to install both languages in order for this to work.

To support Pasdoc, you could create your own Tree-Sitter language definition for Pasdoc and inject it, instead. Or use one of the grammars for similar JavaDoc-like systems, which I'm sure already exist. Injections are managed by the editors using Tree-Sitter, not by the upstream grammars. There is nothing we can do in this repo.

@Isopod Isopod closed this as completed Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants