Utils - skalogryz/editorConfig GitHub Wiki

Utilities unit provide the functions to actually load a .editorconfig file (populating TEditorConfigFile class), perform file lookup, as well as .ini reading utilities.

Utilities unit depends on RTL units: Classes and SysUtils.

If your project is avoiding those units you might not want to use the unit at all. Yet, it would provide you an example of implementation.

Table of Contents

Data Inspection

function GetTabWidth(ec: TEditorConfigEntry; const defVal: integer = -1): integer;
If negative value is returned, then editor's default should be used. Otherwise the specified value should be used.

Per editorConfigs specs, if tab_width property is undefined, indent_size should be used. The function checks for the definition of both properties and returns the corresponding value.

function isTabIndent(const indent_style: string): Boolean;
returns true, if indent_type is set to either "tab" or "tabs" (case-insensitive)

otherwise returns false

function isSpaceIndent(const indent_style: string): Boolean;
returns true, if indent_type is set to either "space" or "spaces" (case-insensitive)

otherwise returns false

EditorConfig LookUp

TLookUpResult

type
  TLookUpResult = record
    editorConfigFile: string;
    filename_pattern: string;

    indent_style : string;  
    indent_size  : integer; 
    tab_width    : integer; 
    end_of_line  : string;  
    charset      : string;  
    trim_trailing_whitespace : TTriBool; 
    insert_final_newline     : TTriBool; 
  end;

The structure is used to return the result of successful look up performed.

  • editorConfigFile - the full file name of .editorconfig file where the configuration was identified
  • filename_pattern - the name of the pattern that specifies the setting (corresponds to name of TEditorConfigEntry)
  • all other fields are copy of the data fields of TEditorConfigEntry

LookupEditorConfig()

function LookupEditorConfig(const FileName: RawByteString; out res: TLookUpResult; IgnoreCase: Boolean = true): Boolean; overload;
Performs a lookup of .editorconfig files for a UTF8 specified file path. If the file AND the editorconfig definition is found, the function would return true, populating ress with non blank values. The function returns false otherwise.

The following overloaded functions

function LookupEditorConfig(const FileName: UnicodeString; out res: TLookUpResult; IgnoreCase: Boolean = true): Boolean; overload;
function LookupEditorConfig(const FileName: WideString; out res: TLookUpResult; IgnoreCase: Boolean = true): Boolean; overload;
provide routines to read the file by it's unicode name. NOTE: internally they convert the file name to UTF8 and are passing the file names to ansi version LookupEditorConfig(). This is the place that might place on Windows with national characters used.

FindMatching()

function FindMatching(const SrchFileName: string; cfg: TEditorConfigFile; IgnoreCase: Boolean): TEditorConfigEntry;
Searches up for "SrchFileName" in the specified configuration file option. Note, that SrchFileName should be a relative file name relative to the directory where configuration file was read from. The function doesn't use filepath property of cfg.
  • IgnoreCase - would ignore the file case when doing pattern matching
procedure InitLookupResult(out lk: TLookupResult);
Initialized result structure. LookupEditorConfig are calling this function, thus you don't have to call it explicitly

Reading

Reading functions are provided for convenience.

ReadFromFile()

procedure ReadFromFile(dst: TEditorConfigFile; const fn: string; usePath: Boolean = true);
  • Reads the .editorconfig from a file stream, where file name is specified by fn property. The file is opened for read, allowing other programs to have any access to the file. The further loading is passed to ReadFromStream()
  • usePath indicates if filepath field of TEditorConfigFile should be populated with the value passed with fn
  • no exceptions are handled by the procedure.

ReadFromStream()

procedure ReadFromStream(dst: TEditorConfigFile; src: TStream);
  • Reads the .editorconfig from stream. The stream is read into TStrings and the data is acutally read from ReadFromStrings()
  • The procedure would not suppress any exceptions thrown during the stream access.

ReadFromStrings()

procedure ReadFromStrings(dst: TEditorConfigFile; str: TStrings);
  • Travels string from top to bottom, using ini parsing routines
  • Each header found becomes an entry in dst editor config. Any invalid or non editorConfig key/values are ignored
  • Only root key/value recognized out of the header. Any other key values met are ignored.

Ini Parsing

NOTE: in future, those routines might be removed entirely for the unit.

These routines are provided only because FPC doesn't provide any easy way to extend IniFiles unit to support "#" char for line comments. (Which is a norm for .editorconfig). Plus the way .editorconfig file is read, doesn't require the hold the entire .ini structure in memory at all time.

Over all the section doesn't really need to be publicly available, yet is still provided, if default ReadXXX routines are not satisfying the requirements.

ParseIniLine()

function ParseIniLine(
  const iniline: string; 
  const cfg: TIniSettings; 
  out line: TIniLine
): Boolean;
  • iniline - a line of text from .ini file
  • cfg - the settings to parse an .ini file
  • line - the description of line parsed
It's expected that a source would be read line by line, and for each line the function would be called. The algorithm would need to track headers occurring and populate the data based of the key/value lines followed after the header.

Keep in mind of the "root" value that's a special exception for .editorConfig files.

TIniLine

The structure describes the parsed .ini file line

  TIniLine = record
    ltype : TIniLineType;
    value : string;
    key   : string;
  end;
  • ltype - type of the line identified:
  • iltComment - it's a comment line, the first character matched the list of comment characters
  • iltKeyValue - it's a key/value pair line "somename=value", value and key are populated with their repsective values
  • iltHeader - it's a header line, like: [name]. Only value field is populated with the name of the header (excluding brackets)
  • iltOther - an empty or invalid line

TIniSettings

The structure that holds options for parsing .editorconfig (.ini) file.

The only option supported right now is the character that starts a comment line.

IniSetting()

The function initialized TIniSettings structure.

procedure IniSetting(out ini: TIniSettings; const AComment: TAnsiCharSet);
  • AComment - specified Ansi-characters set to be used for identifying comments.
⚠️ **GitHub.com Fallback** ⚠️