Module: environment-commands Synopsis: The commands provided by the environment Author: Andy Armstrong Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND /// Environment context define constant $command-prefix-character = ':'; define class () constant slot context-notification :: = make(, lock: make()); constant slot context-project-contexts :: = make(); slot context-project :: false-or() = #f; end class ; define open abstract class () end class ; define open abstract class () end class ; define open abstract class () end class ; define open generic command-library-prompt (context :: , library :: ) => (prompt :: false-or()); define open generic command-library-default-command-class (context :: , library :: ) => (class :: false-or(subclass())); define method command-title (context :: , command :: ) => (title :: ) let command-line = command-line-for-command(context, command); command-line.command-info-title end method command-title; define variable *default-command-library* :: false-or() = #f; define method register-default-command-library (library :: ) => () *default-command-library* := library end method register-default-command-library; define method display-command-prompt (stream :: , context :: ) => () let library = *default-command-library*; let prompt = library & command-library-prompt(context, library); if (prompt) format(stream, prompt) else next-method() end end method display-command-prompt; define method class-for-command-line (context :: , command-line :: , #key start = 0, end: stop = #f) => (class :: subclass(), next-index :: ) let stop :: = stop | command-line.size; case //--- Make sure help always works (as-lowercase(command-line) == "help") => next-method(); start < stop & command-line[start] == $command-prefix-character => next-method(context, command-line, start: start + 1, end: stop); otherwise => let library = *default-command-library*; let default-command = library & command-library-default-command-class(context, library); if (default-command) values(default-command, 0) else next-method() end; end end method class-for-command-line; /// Command superclasses define open abstract class () end class ; define open abstract class () end class ; define method ensure-command-available (context :: , command :: ) => () unless (context.context-project-context) command-error("Project command '%s' requires an open project", command-title(context, command)) end end method ensure-command-available; define method ensure-property-available (context :: , property :: ) => () unless (context.context-project-context) command-error("Project property '%s' requires an open project", property.command-info-title) end end method ensure-property-available; /// Project context define class () slot context-project :: , required-init-keyword: project:; slot context-module :: false-or() = #f, init-keyword: module:; slot context-build-script :: = default-build-script(), init-keyword: build-script:; slot context-properties :: = #(); // slot context-last-heading :: false-or() = #f; slot context-last-item-label :: false-or() = #f; end class ; define method context-project-context (context :: , #key project :: false-or() = context.context-project) => (project-context :: false-or()) project & element(context.context-project-contexts, project, default: #f) end method context-project-context; define method context-project-context-setter (project-context :: false-or(), context :: , #key project :: = context.context-project) => (project-context :: false-or()) let contexts = context.context-project-contexts; if (project-context) element(contexts, project) := project-context else remove-key!(contexts, project); project-context end end method context-project-context-setter; define method context-previous-project (context :: ) => (project :: false-or()) //---*** Use a history... let active-projects = key-sequence(context.context-project-contexts); let projects = remove(active-projects, context.context-project); ~empty?(projects) & projects[0] end method context-previous-project; define method context-library (context :: ) => (library :: false-or()) let module = context & context.context-module; if (module) let project = context.context-project; environment-object-library(project, module) end end method context-library; define method context-library-setter (library :: , context :: ) => (library :: ) let project = context.context-project; let module = library-default-module(project, library); context.context-module := module; library end method context-library-setter;