Issie logo Issie

ComponentLibraries Module

Types and nested modules

Type/Module Description

Constants

ComponentLibrary

A library as offered in the catalogue: a name and a directory. Its components are read when the user opens it, never at startup.

ComponentShape

What a library component becomes on the canvas, without materialising it: the ports its symbol will have, and whether that symbol is drawn as clocked. This is what the catalogue needs to draw a component being carried to the sheet. It is read from the sheet rather than declared in the header for the reason the header gives: nothing derived is stored, so nothing can be out of date with the sheet it describes.

ExportResult

What exporting a library did: how many components were written, and how many were removed from the destination because this library no longer has them.

LibraryFile

A component file: its header, and its sheet as the exact text of a .dgm. The body is a string, not a parsed canvas, so that reading a header never builds one and materialising is a file write followed by the ordinary loader.

LibraryHeader

What the catalogue needs to know about a component without reading its sheet. Deliberately does NOT carry the component's parameters, ports, or anything else derived from the sheet. All of that is read from the body, once, just before it is needed - which is why this cannot drift from the sheet it describes.

LibraryListing

One component of an opened library, as listed.

OpenedLibrary

What opening a library found: the components it can offer, and anything that would not read. A file that will not read costs that component, never the library.

Functions and values

Function or value Description

componentPath libPath name

Full Usage: componentPath libPath name

Parameters:
    libPath : string
    name : string

Returns: string
libPath : string
name : string
Returns: string

copySheetWithNewIds sourcePath newPath

Full Usage: copySheetWithNewIds sourcePath newPath

Parameters:
    sourcePath : string
    newPath : string

Copy a sheet from some source path to a destination path, giving every component, port and connection in it a fresh id so that it cannot clash with the sheet it was copied from. Either path may be a library component or an ordinary sheet, so this is also how a component is copied out of a library into a project and back. Falls back to a plain file copy if the source cannot be read as a sheet.

sourcePath : string
newPath : string

createEmptySheetFile project name

Full Usage: createEmptySheetFile project name

Parameters:
Returns: Result<unit, string>

Create the file for a sheet a project does not have yet, empty.

project : Project
name : string
Returns: Result<unit, string>

customSheetsUsedBy ldc

Full Usage: customSheetsUsedBy ldc

Parameters:
Returns: string list

The sheets a sheet instantiates, by name and without duplicates. Used to fill in a header's Requires when a component is saved, and to find everything that must be saved with it.

ldc : LoadedComponent
Returns: string list

exportLibraryTo destRoot library

Full Usage: exportLibraryTo destRoot library

Parameters:
Returns: Result<ExportResult, string>

Copy a library into `destRoot`, in a subdirectory named after the library - created if it is not there, brought up to date if it is. What lands is a LIBRARY and not a heap of files: the destination ends up holding exactly the components this one holds. A component renamed or deleted since a previous export would otherwise stay behind in the copy and go on being offered from it, which is a library that exists nowhere. Only .ldgm files are touched, and only inside the subdirectory named after the library, so nothing else in the folder the user chose is at risk. The files are copied verbatim rather than read and written back. An .ldgm is a header and the exact text of a .dgm; an export that re-encoded them could differ from its source for reasons that have nothing to do with the components in it. Names are compared case-insensitively when deciding what is stale. On Windows "Adder.ldgm" and "adder.ldgm" ARE the same file, so an exact comparison would delete the one just written; on systems where they differ this errs towards leaving a file alone, which is the safe direction.

destRoot : string
library : ComponentLibrary
Returns: Result<ExportResult, string>

findLibraries ()

Full Usage: findLibraries ()

Parameters:
    () : unit

Returns: ComponentLibrary list

The libraries available: those shipped with Issie, and those the user has made or imported. Directory names only - no file is opened - so this is cheap enough for startup, which it has to be: the catalogue is a pure render function and cannot read the disk itself. Everything about a component is read later, when its library is opened. A user library with the same name as a shipped one wins, so a library can be overridden.

() : unit
Returns: ComponentLibrary list

isLibraryComponentFile filePath

Full Usage: isLibraryComponentFile filePath

Parameters:
    filePath : string

Returns: bool

Whether a sheet's file is a library component rather than an ordinary .dgm.

filePath : string
Returns: bool

isLibraryProject project

Full Usage: isLibraryProject project

Parameters:
Returns: bool

Whether this project IS a library, opened to be edited in place. Read off the sheets' own files rather than carried in the model: the two forms differ only in how each sheet is stored, so the files are where the difference actually is.

project : Project
Returns: bool

isLibrarySheet ldc

Full Usage: isLibrarySheet ldc

Parameters:
Returns: bool

True when a sheet came from a library.

ldc : LoadedComponent
Returns: bool

isManagedLibrary libPath

Full Usage: isManagedLibrary libPath

Parameters:
    libPath : string

Returns: bool

Whether a library is one Issie manages rather than one the user wrote. Two directories are Issie's own. The shipped libraries under the installation are what comes with the program. The user library directory is the store: it is where a library ARRIVES - the copy made when a component is saved into a library from a sheet, and the copy an import will leave - and a copy is not the thing to edit. A library the user is actually working on lives wherever they keep their work, the way a project does.

libPath : string
Returns: bool

libraryIndexFor ldcs libraryName

Full Usage: libraryIndexFor ldcs libraryName

Parameters:
Returns: int

The index to use for a library in this project: the one it already has if any of its sheets are present, otherwise the lowest free index. An index is free when no other library holds it and NO existing sheet begins with its prefix - not merely none of the names this library would produce. User sheet names may themselves contain underscores, so a project can already hold a sheet called L1_Anything, and letting a library share a prefix with an unrelated sheet would be confusing even where nothing actually collides. A prefix in use is skipped rather than anything being renamed or refused.

ldcs : LoadedComponent list
libraryName : string
Returns: int

libraryIsEditable library

Full Usage: libraryIsEditable library

Parameters:
Returns: bool
library : ComponentLibrary
Returns: bool

libraryOfSheet ldc

Full Usage: libraryOfSheet ldc

Parameters:
Returns: (string * int) option

The library and index a sheet belongs to, if it is a library sheet.

ldc : LoadedComponent
Returns: (string * int) option

libraryPathIsEditable libPath

Full Usage: libraryPathIsEditable libPath

Parameters:
    libPath : string

Returns: bool

Whether the library in this directory may be opened as a project and saved again. Not the standard libraries, and not the imported ones: what is in Issie's own directories arrived from somewhere else, and editing a copy in the form it arrived in produces a version that agrees with nothing. A library kept anywhere else is the user's own work and is theirs to change - including one somebody handed them, which they have to put somewhere first. A development run may edit anything, the shipped libraries above all: that is where they are maintained, and the checkout is writable there (see Main/Bridge.fs). Nothing here is prominent, and that is deliberate. Writing a library component is sheet -> save into a library -> place it and try it -> change it, and the last step must not need a second, non-library copy of the sheet kept in step by hand. But it is a thing to go and do rather than a thing to fall into: the catalogue only offers it where it applies, and otherwise a library is opened by navigating to the folder it is in.

libPath : string
Returns: bool

openLibrary library

Full Usage: openLibrary library

Parameters:
Returns: OpenedLibrary

Read the headers of a library's components. Done when the user opens the library, and not kept: it is one small read per component, on an action the user took, and keeping it would mean deciding when it had gone wrong.

library : ComponentLibrary
Returns: OpenedLibrary

prefixFor libraryIndex

Full Usage: prefixFor libraryIndex

Parameters:
    libraryIndex : int

Returns: string

The prefix owned by a library index.

libraryIndex : int
Returns: string

readComponentAndDependencies libPath name

Full Usage: readComponentAndDependencies libPath name

Parameters:
    libPath : string
    name : string

Returns: Result<LibraryFile list, string>

A component and everything it needs, dependencies first - the order they must be written in. Dependencies are named rather than embedded, so they are read from the same library here. A name that is not there is an error rather than a silent omission: the component would otherwise be placed holding a custom component that refers to a sheet which does not exist.

libPath : string
name : string
Returns: Result<LibraryFile list, string>

reservedPrefixOf ldcs sheetName

Full Usage: reservedPrefixOf ldcs sheetName

Parameters:
Returns: string option

The reserved prefix a proposed sheet name would intrude on, if any. Used to refuse the name when a sheet is created or renamed.

ldcs : LoadedComponent list
sheetName : string
Returns: string option

reservedPrefixes ldcs

Full Usage: reservedPrefixes ldcs

Parameters:
Returns: string list

The prefixes the libraries used by this project own. Once a library holds a prefix no sheet may be named into it, or a component of that library added later would have nowhere to go.

ldcs : LoadedComponent list
Returns: string list

sheetExtension project

Full Usage: sheetExtension project

Parameters:
Returns: string

The extension a project's sheets are stored with. A project is all of one form or all of the other, so this is a fact about the project and not about each sheet.

project : Project
Returns: string

sheetFilePath project sheetName

Full Usage: sheetFilePath project sheetName

Parameters:
    project : Project
    sheetName : string

Returns: string

The file one sheet of a project is kept in - including a sheet that is about to be added, which takes the form its siblings are in rather than becoming a stray .dgm the library loader would never read.

project : Project
sheetName : string
Returns: string

sheetNameFor libraryIndex compName

Full Usage: sheetNameFor libraryIndex compName

Parameters:
    libraryIndex : int
    compName : string

Returns: string

The name a library component takes as a sheet of a project.

libraryIndex : int
compName : string
Returns: string

shippedLibrariesDirectory ()

Full Usage: shippedLibrariesDirectory ()

Parameters:
    () : unit

Returns: string

Where the libraries shipped with Issie live: inside the installation, and read-only for anyone who installed it.

() : unit
Returns: string

tryLoadLibraryProject libPath

Full Usage: tryLoadLibraryProject libPath

Parameters:
    libPath : string

Returns: Result<LoadStatus list, string>

Load a library directory as a project: every component in it becomes a sheet, and the file it came from is where it is saved back to. The sheets come back as User whatever the .ldgm says. A library sheet materialised INTO a project is marked Library so that it is hidden and held read-only - it is one thing the user placed, not a sheet of their own design. Here the sheets ARE the design, and marking them that way would open the library into an editor that refuses to edit it. Nor is any of them the top: which component of a library is "the" design is not a question a library answers, and a flag left over from the project a component was authored in would make one of them the answer at random.

libPath : string
Returns: Result<LoadStatus list, string>

tryLoadSheetFile filePath

Full Usage: tryLoadSheetFile filePath

Parameters:
    filePath : string

Returns: Result<LoadedComponent, string>

Read a sheet from its file, in whichever of the two forms that file is.

filePath : string
Returns: Result<LoadedComponent, string>

tryReadComponentFile path

Full Usage: tryReadComponentFile path

Parameters:
    path : string

Returns: Result<LibraryFile, string>

Read one .ldgm. The body comes back as text: there is little to gain from decoding less, since it is a single JSON string token either way.

path : string
Returns: Result<LibraryFile, string>

tryReadComponentShape libPath name

Full Usage: tryReadComponentShape libPath name

Parameters:
    libPath : string
    name : string

Returns: Result<ComponentShape, string>

The shape of one component of a library, read from the same files placing it will read. Every sheet is decoded, not just the component's own: whether it is clocked can depend on a sheet it uses, and its ports come from the last one, which is the component itself.

libPath : string
name : string
Returns: Result<ComponentShape, string>

tryReadHeader path

Full Usage: tryReadHeader path

Parameters:
    path : string

Returns: Result<LibraryHeader, string>

The header of one component.

path : string
Returns: Result<LibraryHeader, string>

trySheetFileBody filePath

Full Usage: trySheetFileBody filePath

Parameters:
    filePath : string

Returns: Result<string, string>

The text of the .dgm a sheet's file holds, unwrapped from its header where it has one. What "save as library component" copies: an .ldgm's body IS a .dgm, so a component can be written into another library from a library opened as a project as readily as from an ordinary sheet.

filePath : string
Returns: Result<string, string>

tryUserLibrariesDirectory ()

Full Usage: tryUserLibrariesDirectory ()

Parameters:
    () : unit

Returns: Result<string, string>

Where libraries the user makes or imports are kept. Those shipped with Issie stay read-only under the installation; this is the writable side. Error when the directory cannot be made - see FilesIO.tryUserDataDirectory for why that is a real possibility and not a theoretical one.

() : unit
Returns: Result<string, string>

unusedLibrarySheets ldcs

Full Usage: unusedLibrarySheets ldcs

Parameters:
Returns: LoadedComponent list

Library sheets no sheet instantiates any more, and so which should be dropped from the project. A library sheet used only by another library sheet of the same component is kept, since that one is reachable; the calculation is repeated until it settles so that a multi-sheet component goes in one piece. Deliberately NOT run when the instance is deleted: undo restores model snapshots, so deleting the sheet there would leave undo unable to bring it back. Sweeping when the project is saved or closed keeps deletion undoable.

ldcs : LoadedComponent list
Returns: LoadedComponent list

writeAllSheetFiles project

Full Usage: writeAllSheetFiles project

Parameters:

Write every sheet of a project to disk. Used where a change reaches sheets other than the open one - a custom component's ports changing shape, and a project being renamed.

project : Project

writeComponentFile libPath header body

Full Usage: writeComponentFile libPath header body

Parameters:
Returns: Result<unit, string>

Write a component into a library, under the name its header carries. What "save as library component" uses; a library opened as a project writes to the file each sheet came from, which is writeComponentFileAt above.

libPath : string
header : LibraryHeader
body : string
Returns: Result<unit, string>

writeComponentFileAt path header body

Full Usage: writeComponentFileAt path header body

Parameters:
Returns: Result<unit, string>

Write a component file to a path chosen by the caller. `body` must be the text of a .dgm exactly as the sheet was saved, since that is what is written back out when it is used.

path : string
header : LibraryHeader
body : string
Returns: Result<unit, string>

writeSheetFile filePath (arg2, arg3, arg4)

Full Usage: writeSheetFile filePath (arg2, arg3, arg4)

Parameters:
Returns: Result<unit, string>

Write one sheet to its own file. The single funnel every sheet save goes through, so that "which kind of project is this" is asked once and in one place.

filePath : string
arg1 : CanvasState
arg2 : SavedWaveInfo option
arg3 : SheetInfo option
Returns: Result<unit, string>

writeSheetFileAt timeStamp filePath (arg3, arg4, arg5)

Full Usage: writeSheetFileAt timeStamp filePath (arg3, arg4, arg5)

Parameters:
Returns: Result<unit, string>

As writeSheetFile, keeping a timestamp the caller already has rather than stamping the moment of writing. For a rewrite the user did not ask for - the id conversion done on load - where the stamp is what says which sheet they were last working on.

timeStamp : DateTime
filePath : string
arg2 : CanvasState
arg3 : SavedWaveInfo option
arg4 : SheetInfo option
Returns: Result<unit, string>

Type something to start searching.