Browse Source

Автодок: языки

Arthur Yefimov 2 years ago
parent
commit
e592390a85

+ 11 - 6
src/Autodoc/Autodoc.Mod

@@ -1,8 +1,11 @@
 MODULE Autodoc;
-IMPORT Files, Texts, Out, Args, Strings, Config, Platform,
+IMPORT Files, Texts, Out, Args, Strings, Platform,
   P := AutodocParser, H := AutodocHtml;
 
 CONST
+  version = '1.0.0-alpha.1';
+  year = 2022;
+
   delim = Platform.PathDelimiter;
 
 TYPE
@@ -74,12 +77,12 @@ PROCEDURE Usage;
 VAR s: ARRAY 256 OF CHAR;
 BEGIN
   Out.String('Free Oberon AutoDoc tool version ');
-  Out.String(Config.version); Out.Ln;
-  Out.String('Copyright (c) 2022-'); Out.Int(Config.year, 0);
+  Out.String(version); Out.Ln;
+  Out.String('Copyright (c) 2022-'); Out.Int(year, 0);
   Out.String(' by Arthur Yefimov and others.'); Out.Ln;
   Out.String('Usage:'); Out.Ln; Args.Get(0, s);
   Out.String('  '); Out.String(s);
-  Out.String(' { "-o" outputPath | sourceFile}'); Out.Ln; Out.Ln;
+  Out.String(' { "-o" outputPath | "--lang" code | sourceFile}'); Out.Ln; Out.Ln;
   Out.String('outputPath is a file name if a single source file is given.');
   Out.Ln;
   Out.String('outputPath is a directory if many source files are given.');
@@ -88,9 +91,9 @@ BEGIN
   Out.String('  '); Out.String(s);
   Out.String(' -o Apples.Mod'); Out.Ln;
   Out.String('  '); Out.String(s);
-  Out.String(' -o doc.html Apples.Mod'); Out.Ln;
+  Out.String(' -o doc.html --lang ru Apples.Mod'); Out.Ln;
   Out.String('  '); Out.String(s);
-  Out.String(' -o docs Fruits.Mod Apples.Mod'); Out.Ln; Out.Ln
+  Out.String(' -o docs Fruits.Mod Apples.Mod'); Out.Ln
 END Usage;
 
 (** Changes extension of the file to '.html'. Puts result is out. *)
@@ -130,6 +133,8 @@ BEGIN
         END
       ELSIF (s = '--inline-style') OR (s = '-i') THEN
         H.SetInlineStyle(TRUE)
+      ELSIF (s = '--lang') OR (i < Args.Count) THEN
+        INC(i); Args.Get(i, s); H.SetLang(s)
       ELSE
         Strings.Copy(s, fnames[fnameCount]);
         INC(fnameCount)

+ 60 - 16
src/Autodoc/AutodocHtml.Mod

@@ -1,8 +1,9 @@
 MODULE AutodocHtml;
-IMPORT Texts, Out, Strings, P := AutodocParser;
+IMPORT Texts, Out, Strings, P := AutodocParser, Env, Lang := SimpleLangs;
 
 CONST
-  styleFname = 'style.css';
+  styleFname = 'Data/style.css';
+  defLang = 'en';
 
 VAR
   PrintObject: PROCEDURE (o: P.Object; indent: INTEGER; inlined: BOOLEAN);
@@ -13,6 +14,31 @@ VAR
   preventSemicol: BOOLEAN;
 
   inlineStyle: BOOLEAN;
+  lang: ARRAY 6 OF CHAR;
+
+(** Language **)
+
+PROCEDURE TryLoadLang(): BOOLEAN;
+VAR ok: BOOLEAN;
+BEGIN ok := FALSE;
+  IF (lang[0] # 0X) & Lang.LangExists(lang) THEN
+    Lang.SetLang(lang); ok := Lang.Done
+  END
+RETURN ok END TryLoadLang;
+
+PROCEDURE LoadLang;
+BEGIN
+  IF ~TryLoadLang() THEN
+    Env.GetLang(lang); lang[2] := 0X;
+    IF ~TryLoadLang() THEN
+      lang := defLang;
+      IF ~TryLoadLang() THEN
+        lang[0] := 0X;
+        Out.String('Could not load language file.'); Out.Ln
+      END
+    END
+  END
+END LoadLang;
 
 (** Printing **)
 
@@ -91,6 +117,7 @@ BEGIN
 END WriteStyle;
 
 PROCEDURE OpenGroup(title: ARRAY OF CHAR; ordinalConsts: BOOLEAN);
+VAR s: ARRAY 256 OF CHAR;
 BEGIN
   WriteLn('<article class="group">');
   Write('<h3 class="group-title">');
@@ -100,9 +127,12 @@ BEGIN
     WriteLn('<div class="ordinal-consts">');
     WriteLn('<table>');
     WriteLn('<thead><tr>');
-    WriteLn('<th class="name">Name</th>');
-    WriteLn('<th class="value">Value</th>');
-    WriteLn('<th class="desc">Description</th>');
+    Write('<th class="name">');
+    Lang.Get('tableColName', s); Write(s); WriteLn('</th>');
+    Write('<th class="value">');
+    Lang.Get('tableColValue', s); Write(s); WriteLn('</th>');
+    Write('<th class="desc">');
+    Lang.Get('tableColDesc', s); Write(s); WriteLn('</th>');
     WriteLn('</tr></thead><tbody>');
   ELSE
     WriteLn('<div class="group-content">')
@@ -282,27 +312,35 @@ BEGIN WriteLn3('<h2 class="heading">', text, '</h2>')
 END BigTitle;
 
 PROCEDURE Header(modName: ARRAY OF CHAR);
+VAR s: ARRAY 256 OF CHAR;
 BEGIN
   WriteLn('<!DOCTYPE html>');
   WriteLn('<html>');
   WriteLn('<head>');
   WriteLn('<meta charset="utf-8">');
-  WriteLn('<title>'); Write(modName);
-  WriteLn(' Module Reference</title>');
+  WriteLn('<title>');
+  Lang.Get('titleBefore', s); Write(s); Write(modName);
+  Lang.Get('titleAfter', s); Write(s);
+  WriteLn('</title>');
   WriteLn('<meta name="viewport" content="width=device-width,initial-scale=1.0">');
   WriteLn('</head>');
   WriteLn('<body>');
   WriteLn('<header class="header"><div class="inner">');
-  Write('<h1>Module <span class="module-name">'); Write(modName);
-  WriteLn('</span> <span class="subtitle">Reference</span></h1>');
+  Write('<h1>'); Lang.Get('headingBefore', s); Write(s);
+  Write('<span class="module-name">'); Write(modName);
+  Lang.Get('headingAfter', s); Write(s);
+  Write('</span> <span class="subtitle">');
+  Lang.Get('headingSubtitle', s); Write(s);
+  WriteLn('</span></h1>');
   WriteLn('</div></header>');
   WriteLn('<main class="main"><div class="inner">');
 END Header;
 
 PROCEDURE Footer;
+VAR s: ARRAY 256 OF CHAR;
 BEGIN
   WriteLn('</div></main><footer class="footer"><div class="inner">');
-  WriteLn('<p>Generated automatically by Free Oberon Autodoc</p>');
+  Write('<p>'); Lang.Get('generatedMsg', s); Write(s); WriteLn('</p>');
  
   WriteLn('</div></footer>');
 
@@ -314,16 +352,17 @@ BEGIN
 END Footer;
 
 PROCEDURE PrintModule(M: P.Module; indent: INTEGER; inlined: BOOLEAN);
+VAR s: ARRAY 64 OF CHAR;
 BEGIN
   Header(M.name);
   PrintComment(M, FALSE);
-  BigTitle('Constants');
+  Lang.Get('constants', s); BigTitle(s);
   PrintList(M.consts, 0, FALSE);
-  BigTitle('Types');
+  Lang.Get('types', s); BigTitle(s);
   PrintList(M.types, 0, FALSE);
-  BigTitle('Variables');
+  Lang.Get('variables', s); BigTitle(s);
   PrintList(M.vars, 0, FALSE);
-  BigTitle('Procedures');
+  Lang.Get('procedures', s); BigTitle(s);
   PrintList(M.procedures, 0, FALSE);
   Footer
 END PrintModule;
@@ -348,9 +387,13 @@ PROCEDURE SetInlineStyle*(inline: BOOLEAN);
 BEGIN inlineStyle := inline
 END SetInlineStyle;
 
+PROCEDURE SetLang*(L: ARRAY OF CHAR);
+BEGIN Strings.Copy(L, lang)
+END SetLang;
+
 PROCEDURE Save*(module: P.Module; fname: ARRAY OF CHAR): BOOLEAN;
 BEGIN
-  NEW(TX); Texts.Open(TX, ''); Texts.OpenWriter(W);
+  LoadLang; NEW(TX); Texts.Open(TX, ''); Texts.OpenWriter(W);
   preventSemicol := FALSE;
   PrintObject(module, 0, FALSE);
   Texts.Append(TX, W.buf); Texts.Close(TX, fname)
@@ -358,5 +401,6 @@ RETURN TRUE END Save;
 
 BEGIN
   PrintObject := PrintObject0;
-  inlineStyle := FALSE
+  inlineStyle := FALSE;
+  lang[0] := 0X
 END AutodocHtml.

+ 1 - 1
src/Autodoc/AutodocParser.Mod

@@ -1,5 +1,5 @@
 MODULE AutodocParser;
-IMPORT Files, Texts, Out, Args, Strings, Config, Platform, Int;
+IMPORT Files, Texts, Out, Strings, Platform, Int;
 CONST
   (** Lexer constants **)
   null    = 0;

+ 0 - 19
src/Autodoc/Config.Mod

@@ -1,19 +0,0 @@
-MODULE Config;
-IMPORT Platform;
-CONST
-  isWindows* = Platform.Windows;
-  stdPath* = 'Programs/';
-
-  version* = '1.1.0-alpha.6';
-  year* = 2022;
-
-VAR
-  debug*: BOOLEAN;
-
-PROCEDURE SetDebug*(deb: BOOLEAN);
-BEGIN debug := deb
-END SetDebug;
-
-BEGIN
-  debug := FALSE
-END Config.

+ 17 - 0
src/Autodoc/Data/Langs/en.dat

@@ -0,0 +1,17 @@
+0 "Error message example"
+
+generatedMsg "Generated automatically by Free Oberon Autodoc"
+constants "Constants"
+types "Types"
+variables "Variables"
+procedures "Procedures"
+
+titleBefore ""
+titleAfter " Module Reference"
+headingBefore "Module "
+headingAfter ""
+headingSubtitle "Reference"
+
+tableColName "Name"
+tableColValue "Value"
+tableColDesc "Description"

+ 17 - 0
src/Autodoc/Data/Langs/ru.dat

@@ -0,0 +1,17 @@
+0 "Пример сообщения об ошибке"
+
+generatedMsg "Сгенерировано автоматически при помощи системы Фри Оберон Автодок"
+constants "Постоянные"
+types "Типы"
+variables "Переменные"
+procedures "Процедуры"
+
+titleBefore ""
+titleAfter " &mdash; справка к модулю"
+headingBefore "Модуль "
+headingAfter ""
+headingSubtitle "Справочный лист"
+
+tableColName "Имя"
+tableColValue "Значение"
+tableColDesc "Описание"

+ 3 - 3
src/Autodoc/Test/style.css → src/Autodoc/Data/style.css

@@ -1,6 +1,6 @@
 @font-face {
-  font-family: 'Inconsolata-LGC';
-  src: url(inconsolatalgcbold.ttf);
+  font-family: 'customfont';
+  src: url(font.ttf);
 }
 
 body, p, h1, h2, h3, h4, h5, h6 {
@@ -9,7 +9,7 @@ body, p, h1, h2, h3, h4, h5, h6 {
 }
 
 body {
-  font-family: 'Inconsolata-LGC', monospace, sans-serif;
+  font-family: customfont, monospace, sans-serif;
   font-size: 14px;
   background: #FBC5AA;
   color: #12365D;

+ 118 - 0
src/Autodoc/SimpleLangs.Mod

@@ -0,0 +1,118 @@
+MODULE SimpleLangs;
+IMPORT Strings, Texts, Int, Dir, Env, Out;
+
+CONST
+  maxErrors* = 500;
+  maxStrings* = 2000;
+  keyLen* = 128;
+  strLen* = 128;
+
+TYPE String* = ARRAY strLen OF CHAR;
+  Pair = RECORD
+    key: ARRAY keyLen OF CHAR;
+    value: ARRAY strLen OF CHAR
+  END;
+
+VAR lang*: ARRAY 6 OF CHAR;
+  errorStr: ARRAY maxErrors OF String;
+  strings: ARRAY maxStrings OF Pair;
+  nofstrings: INTEGER; (* Actual length of strings *)
+  
+  Done*: BOOLEAN;
+
+PROCEDURE Get*(key: ARRAY OF CHAR; VAR value: ARRAY OF CHAR);
+VAR i: INTEGER;
+BEGIN i := 0;
+  WHILE (i # nofstrings) & (strings[i].key # key) DO INC(i) END;
+  IF i # nofstrings THEN Strings.Copy(strings[i].value, value)
+  ELSE Strings.Copy(key, value); Strings.Insert('#', 0, value)
+  END
+END Get;
+
+PROCEDURE Append*(key: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
+VAR s: ARRAY strLen OF CHAR;
+BEGIN Get(key, s); Strings.Append(s, dest)
+END Append;
+
+PROCEDURE GetErrorStr*(err: INTEGER; VAR s: ARRAY OF CHAR);
+BEGIN
+  IF (0 <= err) & (err < LEN(errorStr)) THEN Strings.Copy(errorStr[err], s)
+  ELSE s := 'Text of error #'; Int.Append(err, s); Strings.Append('.', s)
+  END
+END GetErrorStr;
+
+PROCEDURE MakeErrorStr*(err: INTEGER; VAR s: ARRAY OF CHAR);
+VAR z: ARRAY 256 OF CHAR;
+BEGIN
+  GetErrorStr(err, z);
+  s := '#';
+  Int.Append(err, s);
+  Strings.Append(' ', s);
+  Strings.Append(z, s)
+END MakeErrorStr;
+
+PROCEDURE Clear;
+VAR i: INTEGER;
+BEGIN
+  FOR i := 0 TO LEN(errorStr) - 1 DO
+    errorStr[i] := 'STR#';
+    Int.Append(i, errorStr[i])
+  END
+END Clear;
+
+PROCEDURE GetLangFname(lang: ARRAY OF CHAR; VAR fname: ARRAY OF CHAR);
+BEGIN
+  Env.GetAppDir(fname); Strings.Append('Data/Langs/', fname);
+  Strings.Append(lang, fname); Strings.Append('.dat', fname)
+END GetLangFname;
+
+PROCEDURE LoadStrings;
+VAR T: Texts.Text;
+  i: INTEGER;
+  S: Texts.Scanner;
+  fname: ARRAY 256 OF CHAR;
+  key: ARRAY 64 OF CHAR;
+BEGIN
+  Clear;
+  GetLangFname(lang, fname);
+  NEW(T); Texts.Open(T, fname);
+  Texts.OpenScanner(S, T, 0);
+  Texts.Scan(S); Done := TRUE;
+  WHILE ~S.eot & Done DO Done := FALSE;
+    IF S.class = Texts.Int THEN i := S.i; Texts.Scan(S);
+      IF (S.class = Texts.String) & (0 <= i) & (i < LEN(errorStr)) &
+         (S.len < LEN(errorStr[0]) - 1)
+      THEN Strings.Copy(S.s, errorStr[i]); Done := TRUE
+      END
+    ELSIF (S.class = Texts.Name) & (S.len < LEN(key) - 1) THEN
+      Strings.Copy(S.s, key); Texts.Scan(S);
+      IF (S.class = Texts.String) & (0 <= i) & (i < LEN(strings)) &
+         (S.len < LEN(strings[0].value) - 1)
+      THEN
+        IF nofstrings < LEN(strings) THEN Done := TRUE;
+          Strings.Copy(key, strings[nofstrings].key);
+          Strings.Copy(S.s, strings[nofstrings].value);
+          INC(nofstrings)
+        ELSE Out.String('Too many strings in a language file.'); Out.Ln
+        END
+      END
+    END;
+    Texts.Scan(S)
+  END;
+  IF ~Done THEN
+    Out.String('Bad format of "'); Out.String(fname);
+    Out.String('". Line '); Out.Int(S.line, 0); Out.Ln
+  END
+END LoadStrings;
+
+PROCEDURE LangExists*(language: ARRAY OF CHAR): BOOLEAN;
+VAR fname: ARRAY 256 OF CHAR;
+BEGIN GetLangFname(language, fname)
+RETURN Dir.FileExists(fname) END LangExists;
+
+PROCEDURE SetLang*(language: ARRAY OF CHAR);
+BEGIN lang := language; LoadStrings
+END SetLang;
+
+BEGIN Done := TRUE; nofstrings := 0; Clear
+END SimpleLangs.