Browse Source

Cleaning before PR. Note that many tests fail.

yakomaxa 2 years ago
parent
commit
5ba7ba3aac
29 changed files with 1501 additions and 2478 deletions
  1. 12 12
      src/mol-script/script.ts
  2. 13 13
      src/mol-script/transpile.ts
  3. 8 8
      src/mol-script/transpilers/_spec/pymol.spec.ts
  4. 12 12
      src/mol-script/transpilers/_spec/utils.ts
  5. 7 7
      src/mol-script/transpilers/_spec/vmd.spec.ts
  6. 9 9
      src/mol-script/transpilers/all.ts
  7. 13 13
      src/mol-script/transpilers/helper.ts
  8. 2 2
      src/mol-script/transpilers/jmol/examples.ts
  9. 488 488
      src/mol-script/transpilers/jmol/keywords.ts
  10. 30 30
      src/mol-script/transpilers/jmol/markdown-docs.ts
  11. 32 32
      src/mol-script/transpilers/jmol/operators.ts
  12. 221 222
      src/mol-script/transpilers/jmol/parser.ts
  13. 37 539
      src/mol-script/transpilers/jmol/properties.ts
  14. 20 21
      src/mol-script/transpilers/jmol/symbols.ts
  15. 8 8
      src/mol-script/transpilers/pymol/keywords.ts
  16. 4 4
      src/mol-script/transpilers/pymol/operators.ts
  17. 9 10
      src/mol-script/transpilers/pymol/parser.ts
  18. 3 3
      src/mol-script/transpilers/pymol/properties.ts
  19. 2 2
      src/mol-script/transpilers/rasmol/examples.ts
  20. 204 204
      src/mol-script/transpilers/rasmol/keywords.ts
  21. 30 30
      src/mol-script/transpilers/rasmol/markdown-docs.ts
  22. 32 32
      src/mol-script/transpilers/rasmol/operators.ts
  23. 196 197
      src/mol-script/transpilers/rasmol/parser.ts
  24. 43 512
      src/mol-script/transpilers/rasmol/properties.ts
  25. 20 21
      src/mol-script/transpilers/rasmol/symbols.ts
  26. 1 1
      src/mol-script/transpilers/transpiler.ts
  27. 3 3
      src/mol-script/transpilers/vmd/operators.ts
  28. 16 17
      src/mol-script/transpilers/vmd/parser.ts
  29. 26 26
      src/mol-util/monadic-parser.ts

+ 12 - 12
src/mol-script/script.ts

@@ -25,12 +25,12 @@ export { Script };
 
 interface Script { expression: string, language: Script.Language}
 
-function Script(expression: string = "(sel.atom.all)", language: Script.Language = "mol-script"): Script {
+function Script(expression: string = '(sel.atom.all)', language: Script.Language = 'mol-script'): Script {
     return { expression, language };
 }
 
 namespace Script {
-    export type Language = 'mol-script' | 'pymol' | 'vmd' | 'jmol' | 'rasmol' 
+    export type Language = 'mol-script' | 'pymol' | 'vmd' | 'jmol' | 'rasmol'
 
     export function is(x: any): x is Script {
         return !!x && typeof (x as Script).expression === 'string' && !!(x as Script).language;
@@ -42,20 +42,20 @@ namespace Script {
 
     export function toExpression(script: Script): Expression {
         switch (script.language) {
-	case 'mol-script':
+            case 'mol-script':
 	    const parsed = parseMolScript(script.expression);
 	    if (parsed.length === 0) throw new Error('No query');
 	    return transpileMolScript(parsed[0]);
-	case 'pymol':	    
-	    return parse("pymol",script.expression) as Expression;	           
-	case 'jmol':
-	    return parse("jmol",script.expression) as Expression;
-	case 'vmd':
-	    return parse("vmd",script.expression) as Expression;
-	case 'rasmol':
-	    return parse("rasmol",script.expression) as Expression;	   
+            case 'pymol':
+	    return parse('pymol', script.expression) as Expression;
+            case 'jmol':
+	    return parse('jmol', script.expression) as Expression;
+            case 'vmd':
+	    return parse('vmd', script.expression) as Expression;
+            case 'rasmol':
+	    return parse('rasmol', script.expression) as Expression;
         }
- 
+
         throw new Error('unsupported script language');
     }
 

+ 13 - 13
src/mol-script/transpile.ts

@@ -7,22 +7,22 @@
  * Adapted from MolQL src/transpile.ts
  */
 
-import Transpiler from './transpilers/transpiler'
-import _transpiler from './transpilers/all'
-const transpiler: {[index: string]: Transpiler} = _transpiler
+import { Transpiler } from './transpilers/transpiler';
+import { _transpiler } from './transpilers/all';
+const transpiler: {[index: string]: Transpiler} = _transpiler;
 
 export function parse(lang: string, str: string) {
     try {
-	const query = transpiler[lang](str);
-	
-	console.log(str)
-//	console.log(util.inspect(query, {depth: 20, color: true}))
-	console.log('\n')
-	
-	return query;      
+        const query = transpiler[lang](str);
+
+        console.log(str);
+        //	console.log(util.inspect(query, {depth: 20, color: true}))
+        console.log('\n');
+
+        return query;
     } catch (e) {
-	console.log(str)
-	console.log(e.message)
-	console.log('\n')
+        console.log(str);
+        console.log(e.message);
+        console.log('\n');
     }
 }

+ 8 - 8
src/mol-script/transpilers/_spec/pymol.spec.ts

@@ -7,13 +7,13 @@
 
 import * as u from './utils';
 import { parse } from '../../transpile';
-//import { transpiler } from '../pymol/parser';
+// import { transpiler } from '../pymol/parser';
 import { keywords } from '../pymol/keywords';
 import { properties } from '../pymol/properties';
 import { operators } from '../pymol/operators';
 
 /* FAULTY IMPORTS */
-//import compile from '../../compiler';
+// import compile from '../../compiler';
 
 const general = {
     supported: [
@@ -47,14 +47,14 @@ const general = {
 describe('pymol general', () => {
     general.supported.forEach(str => {
         it(str, () => {
-            const expr = parse("pymol",str);
+            const expr = parse('pymol', str);
 	    expect(expr).toThrow();
-  //          compile(expr);
+            //          compile(expr);
         });
     });
     general.unsupported.forEach(str => {
         it(str, () => {
-            const transpileStr = () => parse("pymol",str);
+            const transpileStr = () => parse('pymol', str);
             expect(transpileStr).toThrow();
             expect(transpileStr).not.toThrowError(RangeError);
         });
@@ -72,6 +72,6 @@ describe('pymol general', () => {
 // 'b = 1',
 // 'fc.=.1',
 
-describe('pymol keywords', () => u.testKeywords(keywords, "pymol"));
-describe('pymol operators', () => u.testOperators(operators, "pymol"));
-describe('pymol properties', () => u.testProperties(properties, "pymol"));
+describe('pymol keywords', () => u.testKeywords(keywords, 'pymol'));
+describe('pymol operators', () => u.testOperators(operators, 'pymol'));
+describe('pymol properties', () => u.testProperties(properties, 'pymol'));

+ 12 - 12
src/mol-script/transpilers/_spec/utils.ts

@@ -9,18 +9,18 @@ import { parse } from '../../transpile';
 import { KeywordDict, PropertyDict, OperatorList } from '../types';
 
 /* FAULTY IMPORTS */
-//import compile from '../../compiler';
+// import compile from '../../compiler';
 
-export function testKeywords(keywords: KeywordDict,language: string) {
+export function testKeywords(keywords: KeywordDict, language: string) {
     for (const name in keywords) {
         it(name, () => {
             const k = keywords[name];
             if (k.map) {
-                const expr = parse(language,name);
-  //              compile(expr);
+                const expr = parse(language, name);
+                //              compile(expr);
                 expect(expr).toEqual(k.map());
             } else {
-                const transpile = () => parse(language,name);
+                const transpile = () => parse(language, name);
                 expect(transpile).toThrow();
                 expect(transpile).not.toThrowError(RangeError);
             }
@@ -28,17 +28,17 @@ export function testKeywords(keywords: KeywordDict,language: string) {
     }
 }
 
-export function testProperties(properties: PropertyDict, language : string) {
+export function testProperties(properties: PropertyDict, language: string) {
     for (const name in properties) {
         const p = properties[name];
         p['@examples'].forEach(example => {
             it(name, () => {
                 if (!p.isUnsupported) {
-                    const expr = parse(language,example);
+                    const expr = parse(language, example);
 		    expect(expr).toBe(p);
-//                    compile(expr);
+                    //                    compile(expr);
                 } else {
-                    const transpile = () => parse(language,example);
+                    const transpile = () => parse(language, example);
                     expect(transpile).toThrow();
                     expect(transpile).not.toThrowError(RangeError);
                 }
@@ -52,15 +52,15 @@ export function testProperties(properties: PropertyDict, language : string) {
     }
 }
 
-export function testOperators(operators: OperatorList,language: string) {
+export function testOperators(operators: OperatorList, language: string) {
     operators.forEach(o => {
         o['@examples'].forEach(example => {
             it(o.name, () => {
                 if (!o.isUnsupported) {
-                    const expr = parse(language,example);
+                    const expr = parse(language, example);
 		    expect(expr).toBe(o);
                 } else {
-                    const transpile = () => parse(language,example);
+                    const transpile = () => parse(language, example);
                     expect(transpile).toThrow();
                     expect(transpile).not.toThrowError(RangeError);
                 }

+ 7 - 7
src/mol-script/transpilers/_spec/vmd.spec.ts

@@ -7,14 +7,14 @@
  */
 
 import * as u from './utils';
-//import { transpiler } from '../vmd/parser';
+// import { transpiler } from '../vmd/parser';
 import { parse } from '../../transpile';
 import { keywords } from '../vmd/keywords';
 import { properties } from '../vmd/properties';
 import { operators } from '../vmd/operators';
 
 /* FAULTY IMPORTS */
-//import compile from '../../compiler';
+// import compile from '../../compiler';
 
 const general = {
     supported: [
@@ -46,19 +46,19 @@ const general = {
 describe('vmd general', () => {
     general.supported.forEach(str => {
         it(str, () => {
-            const expr = parse("vmd",str);
+            const expr = parse('vmd', str);
             expect(expr).toThrow();
         });
     });
     general.unsupported.forEach(str => {
         it(str, () => {
-            const transpileStr = () => parse("vmd",str);
+            const transpileStr = () => parse('vmd', str);
             expect(transpileStr).toThrow();
             expect(transpileStr).not.toThrowError(RangeError);
         });
     });
 });
 
-describe('vmd keywords', () => u.testKeywords(keywords, "vmd"));
-describe('vmd operators', () => u.testOperators(operators, "vmd"));
-describe('vmd properties', () => u.testProperties(properties, "vmd"));
+describe('vmd keywords', () => u.testKeywords(keywords, 'vmd'));
+describe('vmd operators', () => u.testOperators(operators, 'vmd'));
+describe('vmd properties', () => u.testProperties(properties, 'vmd'));

+ 9 - 9
src/mol-script/transpilers/all.ts

@@ -1,19 +1,19 @@
- /*
+/*
  * Copyright (c) 2017 MolQL contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import jmol from './jmol/parser'
-//import json from './json/parser'
-//import molQLscript from './molql-script/parser'
-import pymol from './pymol/parser'
-import vmd from './vmd/parser'
-import rasmol from './rasmol/parser'
+import { transpiler as jmol } from './jmol/parser';
+// import json from './json/parser'
+// import molQLscript from './molql-script/parser'
+import { transpiler as pymol } from './pymol/parser';
+import { transpiler as vmd } from './vmd/parser';
+import { transpiler as rasmol } from './rasmol/parser';
 
-export default {
+export const _transpiler = {
     pymol,
     vmd,
     jmol,
     rasmol
-}
+};

+ 13 - 13
src/mol-script/transpilers/helper.ts

@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
  */
-//import * as Q from 'parsimmon';
+// import * as Q from 'parsimmon';
 import * as P from '../../mol-util/monadic-parser';
 import { MolScriptBuilder } from '../../mol-script/language/builder';
 const B = MolScriptBuilder;
@@ -47,11 +47,11 @@ export function postfix(opParser: P.MonadicParser<any>, nextParser: P.MonadicPar
     // INPUT  :: "4!!!"
     // PARSE  :: [4, "factorial", "factorial", "factorial"]
     // REDUCE :: ["factorial", ["factorial", ["factorial", 4]]]
-    return P.MonadicParser.seqMap( /* no seqMap() in monadic-parser.ts, any suitable replacement? */
+    return P.MonadicParser.seqMap(/* no seqMap() in monadic-parser.ts, any suitable replacement? */
         nextParser,
         opParser.many(),
-        (x:any, suffixes:any) =>
-            suffixes.reduce((acc:any, x:any) => {
+        (x: any, suffixes: any) =>
+            suffixes.reduce((acc: any, x: any) => {
                 return mapFn(x, acc);
             }, x)
     );
@@ -95,9 +95,9 @@ export function binaryLeft(opParser: P.MonadicParser<any>, nextParser: P.Monadic
     return P.MonadicParser.seqMap(
         nextParser,
         P.MonadicParser.seq(opParser, nextParser).many(),
-        (first:any, rest:any) => {
-            return rest.reduce((acc:any, ch:any) => {
-                let [op, another] = ch;
+        (first: any, rest: any) => {
+            return rest.reduce((acc: any, ch: any) => {
+                const [op, another] = ch;
                 return mapFn(op, acc, another);
             }, first);
         }
@@ -216,7 +216,7 @@ export function getPropertyRules(properties: PropertyDict) {
     Object.keys(properties).sort(strLenSortFn).forEach(name => {
         const ps = properties[name];
         const errorFn = makeError(`property '${name}' not supported`);
-        const rule = P.MonadicParser.regexp(ps.regex).map((x:any) => {
+        const rule = P.MonadicParser.regexp(ps.regex).map((x: any) => {
             if (ps.isUnsupported) errorFn();
             return testExpr(ps.property, ps.map(x));
         });
@@ -235,7 +235,7 @@ export function getNamedPropertyRules(properties: PropertyDict) {
     Object.keys(properties).sort(strLenSortFn).forEach(name => {
         const ps = properties[name];
         const errorFn = makeError(`property '${name}' not supported`);
-        const rule = P.MonadicParser.regexp(ps.regex).map((x:any) => {
+        const rule = P.MonadicParser.regexp(ps.regex).map((x: any) => {
             if (ps.isUnsupported) errorFn();
             return testExpr(ps.property, ps.map(x));
         });
@@ -247,7 +247,7 @@ export function getNamedPropertyRules(properties: PropertyDict) {
                 nameRule.then(P.MonadicParser.seq(
                     P.MonadicParser.regexp(/>=|<=|=|!=|>|</).trim(P.MonadicParser.optWhitespace),
                     P.MonadicParser.regexp(ps.regex).map(ps.map)
-                )).map((x:any) => {
+                )).map((x: any) => {
                     if (ps.isUnsupported) errorFn();
                     return testExpr(ps.property, { op: x[0], val: x[1] });
                 }).map(groupMap)
@@ -288,10 +288,10 @@ export function getFunctionRules(functions: FunctionDict, argRule: P.MonadicPars
     return functionsList;
 }
 
-//const rule = P.regex(getNamesRegex(name, ps.abbr)).lookahead(lookahead).map(() => {
+// const rule = P.regex(getNamesRegex(name, ps.abbr)).lookahead(lookahead).map(() => {
 //    if (ps.isUnsupported) errorFn()
 //    return ps.property
-//})
+// })
 
 export function getPropertyNameRules(properties: PropertyDict, lookahead: RegExp) {
     const list: P.MonadicParser<any>[] = [];
@@ -357,7 +357,7 @@ const entityProps = ['entityKey', 'label_entity_id', 'entityType'];
 const chainProps = ['chainKey', 'label_asym_id', 'label_entity_id', 'auth_asym_id', 'entityType'];
 const residueProps = ['residueKey', 'label_comp_id', 'label_seq_id', 'auth_comp_id', 'auth_seq_id', 'pdbx_formal_charge', 'secondaryStructureKey', 'secondaryStructureFlags', 'isModified', 'modifiedParentName'];
 export function testLevel(property: any) {
-   if (property.head.startsWith(propPrefix)) {
+    if (property.head.startsWith(propPrefix)) {
         const name = property.head.substr(propPrefix.length);
         if (entityProps.indexOf(name) !== -1) return 'entity-test' as string;
         if (chainProps.indexOf(name) !== -1) return 'chain-test' as string;

+ 2 - 2
src/mol-script/transpilers/jmol/examples.ts

@@ -5,7 +5,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-export default [{
+export const jmolSelectionsExamples = [{
     name: 'Residue 50 or 135',
     value: '50 or 135'
 }, {
@@ -23,4 +23,4 @@ export default [{
 }, {
     name: 'Pyrimidine residues',
     value: 'pyrimidine'
-}]
+}];

+ 488 - 488
src/mol-script/transpilers/jmol/keywords.ts

@@ -1,5 +1,5 @@
-/**                                                                                                                                        
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+/**
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                      * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                 *
  * @author Koya Sakuma                                                                                                                       * This module was taken from MolQL and modified in similar manner as pymol and vmd tranpilers.
 **/
@@ -12,504 +12,504 @@ import { KeywordDict } from '../types';
 
 
 function nucleicExpr() {
-  return B.struct.combinator.merge([
-    B.struct.generator.atomGroups({
-      'residue-test': B.core.set.has([
-        B.set(...['G', 'C', 'A', 'T', 'U', 'I', 'DG', 'DC', 'DA', 'DT', 'DU', 'DI', '+G', '+C', '+A', '+T', '+U', '+I']),
-        B.ammp('label_comp_id')
-      ])
-    }),
-    B.struct.filter.pick({
-      0: B.struct.generator.atomGroups({
-        'group-by': B.ammp('residueKey')
-      }),
-      test: B.core.logic.and([
-        B.core.rel.eq([ B.struct.atomSet.atomCount(), 1 ]),
-        B.core.rel.eq([ B.ammp('label_atom_id'), B.atomName('P') ]),
-      ])
-    }),
-    B.struct.filter.pick({
-      0: B.struct.generator.atomGroups({
-        'group-by': B.ammp('residueKey')
-      }),
-      test: B.core.logic.or([
-        B.core.set.isSubset([
-          h.atomNameSet([ "C1'", "C2'", "O3'", "C3'", "C4'", "C5'", "O5'" ]),
-          B.ammpSet('label_atom_id')
-        ]),
-        B.core.set.isSubset([
-          h.atomNameSet([ 'C1*', 'C2*', 'O3*', 'C3*', 'C4*', 'C5*', 'O5*' ]),
-          B.ammpSet('label_atom_id')
-        ])
-      ])
-    })
-  ])
+    return B.struct.combinator.merge([
+        B.struct.generator.atomGroups({
+            'residue-test': B.core.set.has([
+                B.set(...['G', 'C', 'A', 'T', 'U', 'I', 'DG', 'DC', 'DA', 'DT', 'DU', 'DI', '+G', '+C', '+A', '+T', '+U', '+I']),
+                B.ammp('label_comp_id')
+            ])
+        }),
+        B.struct.filter.pick({
+            0: B.struct.generator.atomGroups({
+                'group-by': B.ammp('residueKey')
+            }),
+            test: B.core.logic.and([
+                B.core.rel.eq([B.struct.atomSet.atomCount(), 1]),
+                B.core.rel.eq([B.ammp('label_atom_id'), B.atomName('P')]),
+            ])
+        }),
+        B.struct.filter.pick({
+            0: B.struct.generator.atomGroups({
+                'group-by': B.ammp('residueKey')
+            }),
+            test: B.core.logic.or([
+                B.core.set.isSubset([
+                    h.atomNameSet(["C1'", "C2'", "O3'", "C3'", "C4'", "C5'", "O5'"]),
+                    B.ammpSet('label_atom_id')
+                ]),
+                B.core.set.isSubset([
+                    h.atomNameSet(['C1*', 'C2*', 'O3*', 'C3*', 'C4*', 'C5*', 'O5*']),
+                    B.ammpSet('label_atom_id')
+                ])
+            ])
+        })
+    ]);
 }
 
 const ResDict = {
-  acidic: ['ASP', 'GLU'],
-  aliphatic: ['ALA', 'GLY', 'ILE', 'LEU', 'VAL'],
-  amino: ['ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL', 'ASX', 'GLX', 'UNK', ],
-  aromatic: ['HIS', 'PHE', 'TRP', 'TYR'],
-  basic: ['ARG', 'HIS', 'LYS'],
-  buried: ['ALA','CYS', 'ILE', 'LEU', 'MET', 'PHE', 'TRP', 'VAL'],
-  cg: ['CYT', 'C', 'GUA', 'G'],
-  cyclic: ['HIS', 'PHE', 'PRO', 'TRP', 'TYR'],
-  hydrophobic: ['ALA', 'GLY', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'TYR', 'VAL'],
-  large: ['ARG', 'GLU', 'GLN', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'TRP', 'TYR'],
-  medium: ['ASN', 'ASP', 'CYS', 'PRO', 'THR', 'VAL'],
-  small: ['ALA', 'GLY', 'SER'],
-}
+    acidic: ['ASP', 'GLU'],
+    aliphatic: ['ALA', 'GLY', 'ILE', 'LEU', 'VAL'],
+    amino: ['ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL', 'ASX', 'GLX', 'UNK'],
+    aromatic: ['HIS', 'PHE', 'TRP', 'TYR'],
+    basic: ['ARG', 'HIS', 'LYS'],
+    buried: ['ALA', 'CYS', 'ILE', 'LEU', 'MET', 'PHE', 'TRP', 'VAL'],
+    cg: ['CYT', 'C', 'GUA', 'G'],
+    cyclic: ['HIS', 'PHE', 'PRO', 'TRP', 'TYR'],
+    hydrophobic: ['ALA', 'GLY', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'TYR', 'VAL'],
+    large: ['ARG', 'GLU', 'GLN', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'TRP', 'TYR'],
+    medium: ['ASN', 'ASP', 'CYS', 'PRO', 'THR', 'VAL'],
+    small: ['ALA', 'GLY', 'SER'],
+};
 
 export const keywords: KeywordDict = {
-  // general terms
-  all: {
-    '@desc': 'all atoms; same as *',
-    abbr: ['*'],
-    map: () => B.struct.generator.all()
-  },
-  bonded: {
-    '@desc': 'covalently bonded',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.rel.gr([B.struct.atomProperty.core.bondCount({
-        flags: B.struct.type.bondFlags(['covalent', 'metallic', 'sulfide'])
-      }), 0])
-    })
-  },
-  clickable: {
-    '@desc': 'actually visible -- having some visible aspect such as wireframe, spacefill, or a label showing, or the alpha-carbon or phosphorus atom in a biomolecule that is rendered with only cartoon, rocket, or other biomolecule-specific shape.'
-  },
-  connected: {
-    '@desc': 'bonded in any way, including hydrogen bonds',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.rel.gr([B.struct.atomProperty.core.bondCount({
-        flags: B.struct.type.bondFlags()
-      }), 0])
-    })
-  },
-  displayed: {
-    '@desc': 'displayed using the display or hide command; not necessarily visible'
-  },
-  hidden: {
-    '@desc': 'hidden using the display or hide command'
-  },
-  none: {
-    '@desc': 'no atoms',
-    map: () => B.struct.generator.empty()
-  },
-  selected: {
-    '@desc': 'atoms that have been selected; defaults to all when a file is first loaded'
-  },
-  thisModel: {
-    '@desc': 'atoms in the current frame set, as defined by frame, model, or animation commands. If more than one model is in this set, "thisModel" refers to all of them, regardless of atom displayed/hidden status.'
-  },
-  visible: {
-    '@desc': 'visible in any way, including PDB residue atoms for which a cartoon or other such rendering makes their group visible, even if they themselves are not visible.'
-  },
-  subset: {
-    '@desc': 'the currently defined subset. Note that if a subset is currently defined, then select/display all is the same as select/display subset, restrict none is the same as restrict not subset. In addition, select not subset selects nothing.'
-  },
-  specialPosition: {
-    '@desc': 'atoms in crystal structures that are at special positions - that is, for which there is more than one operator that leads to them.'
-  },
-  unitcell: {
-    '@desc': 'atoms within the current unitcell, which may be offset. This includes atoms on the faces and at the vertices of the unitcell.'
-  },
-  polyhedra: {
-    '@desc': 'all central atoms for which polyhedra have been created. See also polyhera(n), below. (Jmol 14.4)'
-  },
-  nonmetal: {
-    '@desc': '_H,_He,_B,_C,_N,_O,_F,_Ne,_Si,_P,_S,_Cl,_Ar,_As,_Se,_Br,_Kr,_Te,_I,_Xe,_At,_Rn',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.set.has([
-        B.set(...['H','He','B','C','N','O','F','Ne','Si','P','S','Cl','Ar','As','Se','Br','Kr','Te','I','Xe','At','Rn'].map(B.es)),
-        B.acp('elementSymbol')
-      ])
-    })
-  },
-  metal: {
-    '@desc': '!nonmetal',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.logic.not([
-        B.core.set.has([
-          B.set(...['H','He','B','C','N','O','F','Ne','Si','P','S','Cl','Ar','As','Se','Br','Kr','Te','I','Xe','At','Rn'].map(B.es)),
-          B.acp('elementSymbol')
-        ])
-      ])
-    })
-  },
-  alkaliMetal: {
-    '@desc': '_Li,_Na,_K,_Rb,_Cs,_Fr',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.set.has([
-        B.set(...['Li','Na','K','Rb','Cs','Fr'].map(B.es)),
-        B.acp('elementSymbol')
-      ])
-    })
-  },
-  alkalineEarth: {
-    '@desc': '_Be,_Mg,_Ca,_Sr,_Ba,_Ra',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.set.has([
-        B.set(...['Be','Mg','Ca','Sr','Ba','Ra'].map(B.es)),
-        B.acp('elementSymbol')
-      ])
-    })
-  },
-  nobleGas: {
-    '@desc': '_He,_Ne,_Ar,_Kr,_Xe,_Rn',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.set.has([
-        B.set(...['He','Ne','Ar','Kr','Xe','Rn'].map(B.es)),
-        B.acp('elementSymbol')
-      ])
-    })
-  },
-  metalloid: {
-    '@desc': '_B,_Si,_Ge,_As,_Sb,_Te',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.set.has([
-        B.set(...['B','Si','Ge','As','Sb','Te'].map(B.es)),
-        B.acp('elementSymbol')
-      ])
-    })
-  },
-  transitionMetal: {
-    '@desc': '(includes La and Ac) elemno>=21 and elemno<=30, elemno=57, elemno=89, elemno>=39 and elemno<=48, elemno>=72 and elemno<=80, elemno>=104 and elemno<=112',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.logic.or([
-        B.core.rel.inRange([B.acp('atomicNumber'), 21, 30]),
-        B.core.rel.inRange([B.acp('atomicNumber'), 39, 48]),
-        B.core.rel.inRange([B.acp('atomicNumber'), 72, 80]),
-        B.core.rel.inRange([B.acp('atomicNumber'), 104, 112]),
-        B.core.set.has([B.set(57, 89), B.acp('atomicNumber')])
-      ])
-    })
-  },
-  lanthanide: {
-    '@desc': '(does not include La) elemno>57 and elemno<=71',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.rel.inRange([B.acp('atomicNumber'), 57, 71])
-    })
-  },
-  actinide: {
-    '@desc': '(does not include Ac) elemno>89 and elemno<=103',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.rel.inRange([B.acp('atomicNumber'), 89, 103])
-    })
-  },
-  isaromatic: {
-    '@desc': 'atoms connected with the AROMATIC, AROMATICSINGLE, or AROMATICDOUBLE bond types',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.rel.gr([
-        B.struct.atomProperty.core.bondCount({
-          flags: B.struct.type.bondFlags(['aromatic'])
-        }),
-        0
-      ])
-    })
-  },
+    // general terms
+    all: {
+        '@desc': 'all atoms; same as *',
+        abbr: ['*'],
+        map: () => B.struct.generator.all()
+    },
+    bonded: {
+        '@desc': 'covalently bonded',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.rel.gr([B.struct.atomProperty.core.bondCount({
+                flags: B.struct.type.bondFlags(['covalent', 'metallic', 'sulfide'])
+            }), 0])
+        })
+    },
+    clickable: {
+        '@desc': 'actually visible -- having some visible aspect such as wireframe, spacefill, or a label showing, or the alpha-carbon or phosphorus atom in a biomolecule that is rendered with only cartoon, rocket, or other biomolecule-specific shape.'
+    },
+    connected: {
+        '@desc': 'bonded in any way, including hydrogen bonds',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.rel.gr([B.struct.atomProperty.core.bondCount({
+                flags: B.struct.type.bondFlags()
+            }), 0])
+        })
+    },
+    displayed: {
+        '@desc': 'displayed using the display or hide command; not necessarily visible'
+    },
+    hidden: {
+        '@desc': 'hidden using the display or hide command'
+    },
+    none: {
+        '@desc': 'no atoms',
+        map: () => B.struct.generator.empty()
+    },
+    selected: {
+        '@desc': 'atoms that have been selected; defaults to all when a file is first loaded'
+    },
+    thisModel: {
+        '@desc': 'atoms in the current frame set, as defined by frame, model, or animation commands. If more than one model is in this set, "thisModel" refers to all of them, regardless of atom displayed/hidden status.'
+    },
+    visible: {
+        '@desc': 'visible in any way, including PDB residue atoms for which a cartoon or other such rendering makes their group visible, even if they themselves are not visible.'
+    },
+    subset: {
+        '@desc': 'the currently defined subset. Note that if a subset is currently defined, then select/display all is the same as select/display subset, restrict none is the same as restrict not subset. In addition, select not subset selects nothing.'
+    },
+    specialPosition: {
+        '@desc': 'atoms in crystal structures that are at special positions - that is, for which there is more than one operator that leads to them.'
+    },
+    unitcell: {
+        '@desc': 'atoms within the current unitcell, which may be offset. This includes atoms on the faces and at the vertices of the unitcell.'
+    },
+    polyhedra: {
+        '@desc': 'all central atoms for which polyhedra have been created. See also polyhera(n), below. (Jmol 14.4)'
+    },
+    nonmetal: {
+        '@desc': '_H,_He,_B,_C,_N,_O,_F,_Ne,_Si,_P,_S,_Cl,_Ar,_As,_Se,_Br,_Kr,_Te,_I,_Xe,_At,_Rn',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.set.has([
+                B.set(...['H', 'He', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Si', 'P', 'S', 'Cl', 'Ar', 'As', 'Se', 'Br', 'Kr', 'Te', 'I', 'Xe', 'At', 'Rn'].map(B.es)),
+                B.acp('elementSymbol')
+            ])
+        })
+    },
+    metal: {
+        '@desc': '!nonmetal',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.logic.not([
+                B.core.set.has([
+                    B.set(...['H', 'He', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Si', 'P', 'S', 'Cl', 'Ar', 'As', 'Se', 'Br', 'Kr', 'Te', 'I', 'Xe', 'At', 'Rn'].map(B.es)),
+                    B.acp('elementSymbol')
+                ])
+            ])
+        })
+    },
+    alkaliMetal: {
+        '@desc': '_Li,_Na,_K,_Rb,_Cs,_Fr',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.set.has([
+                B.set(...['Li', 'Na', 'K', 'Rb', 'Cs', 'Fr'].map(B.es)),
+                B.acp('elementSymbol')
+            ])
+        })
+    },
+    alkalineEarth: {
+        '@desc': '_Be,_Mg,_Ca,_Sr,_Ba,_Ra',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.set.has([
+                B.set(...['Be', 'Mg', 'Ca', 'Sr', 'Ba', 'Ra'].map(B.es)),
+                B.acp('elementSymbol')
+            ])
+        })
+    },
+    nobleGas: {
+        '@desc': '_He,_Ne,_Ar,_Kr,_Xe,_Rn',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.set.has([
+                B.set(...['He', 'Ne', 'Ar', 'Kr', 'Xe', 'Rn'].map(B.es)),
+                B.acp('elementSymbol')
+            ])
+        })
+    },
+    metalloid: {
+        '@desc': '_B,_Si,_Ge,_As,_Sb,_Te',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.set.has([
+                B.set(...['B', 'Si', 'Ge', 'As', 'Sb', 'Te'].map(B.es)),
+                B.acp('elementSymbol')
+            ])
+        })
+    },
+    transitionMetal: {
+        '@desc': '(includes La and Ac) elemno>=21 and elemno<=30, elemno=57, elemno=89, elemno>=39 and elemno<=48, elemno>=72 and elemno<=80, elemno>=104 and elemno<=112',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.logic.or([
+                B.core.rel.inRange([B.acp('atomicNumber'), 21, 30]),
+                B.core.rel.inRange([B.acp('atomicNumber'), 39, 48]),
+                B.core.rel.inRange([B.acp('atomicNumber'), 72, 80]),
+                B.core.rel.inRange([B.acp('atomicNumber'), 104, 112]),
+                B.core.set.has([B.set(57, 89), B.acp('atomicNumber')])
+            ])
+        })
+    },
+    lanthanide: {
+        '@desc': '(does not include La) elemno>57 and elemno<=71',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.rel.inRange([B.acp('atomicNumber'), 57, 71])
+        })
+    },
+    actinide: {
+        '@desc': '(does not include Ac) elemno>89 and elemno<=103',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.rel.inRange([B.acp('atomicNumber'), 89, 103])
+        })
+    },
+    isaromatic: {
+        '@desc': 'atoms connected with the AROMATIC, AROMATICSINGLE, or AROMATICDOUBLE bond types',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.rel.gr([
+                B.struct.atomProperty.core.bondCount({
+                    flags: B.struct.type.bondFlags(['aromatic'])
+                }),
+                0
+            ])
+        })
+    },
 
-  carbohydrate: {
-    '@desc': ''
-  },
-  ions: {
-    '@desc': '(specifically the PDB designations "PO4" and "SO4")'
-  },
-  ligand: {
-    '@desc': '(originally "hetero and not solvent"; changed to "!(protein,nucleic,water,UREA)" for Jmol 12.2)'
-  },
-  nucleic: {
-    '@desc': 'any group that (a) has one of the following group names: G, C, A, T, U, I, DG, DC, DA, DT, DU, DI, +G, +C, +A, +T, +U, +I; or (b) can be identified as a group that is only one atom, with name "P"; or (c) has all of the following atoms (prime, \', can replace * here): C1*, C2*, C3*, O3*, C4*, C5*, and O5*.',
-    map: () => nucleicExpr()
-  },
-  purine: {
-    '@desc': 'any nucleic group that (a) has one of the following group names: A, G, I, DA, DG, DI, +A, +G, or +I; or (b) also has atoms N7, C8, and N9.',
-    map: () => B.struct.modifier.intersectBy({
-      0: nucleicExpr(),
-      by: B.struct.combinator.merge([
-        B.struct.generator.atomGroups({
-          'residue-test': B.core.set.has([
-            B.set(...['A', 'G', 'I', 'DA', 'DG', 'DI', '+A', '+G', '+I']),
-            B.ammp('label_comp_id')
-          ])
-        }),
-        B.struct.filter.pick({
-          0: B.struct.generator.atomGroups({
-            'group-by': B.ammp('residueKey')
-          }),
-          test: B.core.set.isSubset([
-            h.atomNameSet([ 'N7', 'C8', 'N9' ]),
-            B.ammpSet('label_atom_id')
-          ])
+    carbohydrate: {
+        '@desc': ''
+    },
+    ions: {
+        '@desc': '(specifically the PDB designations "PO4" and "SO4")'
+    },
+    ligand: {
+        '@desc': '(originally "hetero and not solvent"; changed to "!(protein,nucleic,water,UREA)" for Jmol 12.2)'
+    },
+    nucleic: {
+        '@desc': 'any group that (a) has one of the following group names: G, C, A, T, U, I, DG, DC, DA, DT, DU, DI, +G, +C, +A, +T, +U, +I; or (b) can be identified as a group that is only one atom, with name "P"; or (c) has all of the following atoms (prime, \', can replace * here): C1*, C2*, C3*, O3*, C4*, C5*, and O5*.',
+        map: () => nucleicExpr()
+    },
+    purine: {
+        '@desc': 'any nucleic group that (a) has one of the following group names: A, G, I, DA, DG, DI, +A, +G, or +I; or (b) also has atoms N7, C8, and N9.',
+        map: () => B.struct.modifier.intersectBy({
+            0: nucleicExpr(),
+            by: B.struct.combinator.merge([
+                B.struct.generator.atomGroups({
+                    'residue-test': B.core.set.has([
+                        B.set(...['A', 'G', 'I', 'DA', 'DG', 'DI', '+A', '+G', '+I']),
+                        B.ammp('label_comp_id')
+                    ])
+                }),
+                B.struct.filter.pick({
+                    0: B.struct.generator.atomGroups({
+                        'group-by': B.ammp('residueKey')
+                    }),
+                    test: B.core.set.isSubset([
+                        h.atomNameSet(['N7', 'C8', 'N9']),
+                        B.ammpSet('label_atom_id')
+                    ])
+                })
+            ])
         })
-      ])
-    })
-  },
-  pyrimidine: {
-    '@desc': 'any nucleic group that (a) has one of the following group names: C, T, U, DC, DT, DU, +C, +T, +U; or (b) also has atom O2.',
-    map: () => B.struct.modifier.intersectBy({
-      0: nucleicExpr(),
-      by: B.struct.combinator.merge([
-        B.struct.generator.atomGroups({
-          'residue-test': B.core.set.has([
-            B.set(...['C', 'T', 'U', 'DC', 'DT', 'DU', '+C', '+T', '+U']),
-            B.ammp('label_comp_id')
-          ])
-        }),
-        B.struct.filter.pick({
-          0: B.struct.generator.atomGroups({
-            'group-by': B.ammp('residueKey')
-          }),
-          test: B.core.logic.or([
-            B.core.set.has([
-              B.ammpSet('label_atom_id'),
-              B.atomName('O2*')
-            ]),
-            B.core.set.has([
-              B.ammpSet('label_atom_id'),
-              B.atomName("O2'")
+    },
+    pyrimidine: {
+        '@desc': 'any nucleic group that (a) has one of the following group names: C, T, U, DC, DT, DU, +C, +T, +U; or (b) also has atom O2.',
+        map: () => B.struct.modifier.intersectBy({
+            0: nucleicExpr(),
+            by: B.struct.combinator.merge([
+                B.struct.generator.atomGroups({
+                    'residue-test': B.core.set.has([
+                        B.set(...['C', 'T', 'U', 'DC', 'DT', 'DU', '+C', '+T', '+U']),
+                        B.ammp('label_comp_id')
+                    ])
+                }),
+                B.struct.filter.pick({
+                    0: B.struct.generator.atomGroups({
+                        'group-by': B.ammp('residueKey')
+                    }),
+                    test: B.core.logic.or([
+                        B.core.set.has([
+                            B.ammpSet('label_atom_id'),
+                            B.atomName('O2*')
+                        ]),
+                        B.core.set.has([
+                            B.ammpSet('label_atom_id'),
+                            B.atomName("O2'")
+                        ])
+                    ])
+                })
             ])
-          ])
         })
-      ])
-    })
-  },
-  dna: {
-    '@desc': 'any nucleic group that (a) has one of the following group names: DG, DC, DA, DT, DU, DI, T, +G, +C, +A, +T; or (b) has neither atom O2* or O2\'.',
-    map: () => B.struct.modifier.intersectBy({
-      0: nucleicExpr(),
-      by: B.struct.combinator.merge([
-        B.struct.generator.atomGroups({
-          'residue-test': B.core.set.has([
-            B.set(...['DG', 'DC', 'DA', 'DT', 'DU', 'DI', 'T', '+G', '+C', '+A', '+T']),
-            B.ammp('label_comp_id')
-          ])
-        }),
-        B.struct.filter.pick({
-          0: B.struct.generator.atomGroups({
-            'group-by': B.ammp('residueKey')
-          }),
-          test: B.core.logic.not([
-            B.core.logic.or([
-              B.core.set.has([
-                B.ammpSet('label_atom_id'),
-                B.atomName('O2*')
-              ]),
-              B.core.set.has([
-                B.ammpSet('label_atom_id'),
-                B.atomName("O2'")
-              ])
+    },
+    dna: {
+        '@desc': 'any nucleic group that (a) has one of the following group names: DG, DC, DA, DT, DU, DI, T, +G, +C, +A, +T; or (b) has neither atom O2* or O2\'.',
+        map: () => B.struct.modifier.intersectBy({
+            0: nucleicExpr(),
+            by: B.struct.combinator.merge([
+                B.struct.generator.atomGroups({
+                    'residue-test': B.core.set.has([
+                        B.set(...['DG', 'DC', 'DA', 'DT', 'DU', 'DI', 'T', '+G', '+C', '+A', '+T']),
+                        B.ammp('label_comp_id')
+                    ])
+                }),
+                B.struct.filter.pick({
+                    0: B.struct.generator.atomGroups({
+                        'group-by': B.ammp('residueKey')
+                    }),
+                    test: B.core.logic.not([
+                        B.core.logic.or([
+                            B.core.set.has([
+                                B.ammpSet('label_atom_id'),
+                                B.atomName('O2*')
+                            ]),
+                            B.core.set.has([
+                                B.ammpSet('label_atom_id'),
+                                B.atomName("O2'")
+                            ])
+                        ])
+                    ])
+                })
             ])
-          ])
         })
-      ])
-    })
-  },
-  rna: {
-    '@desc': 'any nucleic group that (a) has one of the following group names: G, C, A, U, I, +U, +I; or (b) has atom O2* or O2\'.',
-    map: () => B.struct.modifier.intersectBy({
-      0: nucleicExpr(),
-      by: B.struct.combinator.merge([
-        B.struct.generator.atomGroups({
-          'residue-test': B.core.set.has([
-            B.set(...['G', 'C', 'A', 'U', 'I', '+U', '+I']),
-            B.ammp('label_comp_id')
-          ])
-        }),
-        B.struct.filter.pick({
-          0: B.struct.generator.atomGroups({
-            'group-by': B.ammp('residueKey')
-          }),
-          test: B.core.logic.or([
-            B.core.set.has([
-              B.ammpSet('label_atom_id'),
-              B.atomName('O2*')
-            ]),
-            B.core.set.has([
-              B.ammpSet('label_atom_id'),
-              B.atomName("O2'")
+    },
+    rna: {
+        '@desc': 'any nucleic group that (a) has one of the following group names: G, C, A, U, I, +U, +I; or (b) has atom O2* or O2\'.',
+        map: () => B.struct.modifier.intersectBy({
+            0: nucleicExpr(),
+            by: B.struct.combinator.merge([
+                B.struct.generator.atomGroups({
+                    'residue-test': B.core.set.has([
+                        B.set(...['G', 'C', 'A', 'U', 'I', '+U', '+I']),
+                        B.ammp('label_comp_id')
+                    ])
+                }),
+                B.struct.filter.pick({
+                    0: B.struct.generator.atomGroups({
+                        'group-by': B.ammp('residueKey')
+                    }),
+                    test: B.core.logic.or([
+                        B.core.set.has([
+                            B.ammpSet('label_atom_id'),
+                            B.atomName('O2*')
+                        ]),
+                        B.core.set.has([
+                            B.ammpSet('label_atom_id'),
+                            B.atomName("O2'")
+                        ])
+                    ])
+                })
             ])
-          ])
         })
-      ])
-    })
-  },
-  protein: {
-    '@desc': 'defined as a group that (a) has one of the following group names: ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, ASX, GLX, or UNK; or (b) contains PDB atom designations [C, O, CA, and N] bonded correctly; or (c) does not contain "O" but contains [C, CA, and N] bonded correctly; or (d) has only one atom, which has name CA and does not have the group name CA (indicating a calcium atom).'
-  },
-  acidic: {
-    '@desc': 'ASP GLU',
-    map: () => h.resnameExpr(ResDict.acidic)
-  },
-  acyclic: {
-    '@desc': 'amino and not cyclic',
-    map: () => B.struct.modifier.intersectBy({
-      0: h.resnameExpr(ResDict.amino),
-      by: h.invertExpr(h.resnameExpr(ResDict.cyclic))
-    })
-  },
-  aliphatic: {
-    '@desc': 'ALA GLY ILE LEU VAL',
-    map: () => h.resnameExpr(ResDict.aliphatic)
-  },
-  amino: {
-    '@desc': 'all twenty standard amino acids, plus ASX, GLX, UNK',
-    map: () => h.resnameExpr(ResDict.amino)
-  },
-  aromatic: {
-    '@desc': 'HIS PHE TRP TYR (see also "isaromatic" for aromatic bonds)',
-    map: () => h.resnameExpr(ResDict.aromatic)
-  },
-  basic: {
-    '@desc': 'ARG HIS LYS',
-    map: () => h.resnameExpr(ResDict.basic)
-  },
-  buried: {
-    '@desc': 'ALA CYS ILE LEU MET PHE TRP VAL',
-    map: () => h.resnameExpr(ResDict.buried)
-  },
-  charged: {
-    '@desc': 'same as acidic or basic -- ASP GLU, ARG HIS LYS',
-    map: () => h.resnameExpr(ResDict.acidic.concat(ResDict.basic))
-  },
-  cyclic: {
-    '@desc': 'HIS PHE PRO TRP TYR',
-    map: () => h.resnameExpr(ResDict.cyclic)
-  },
-  helix: {
-    '@desc': 'secondary structure-related.',
-    map: () => B.struct.generator.atomGroups({
-      'residue-test': B.core.flags.hasAny([
-        B.struct.type.secondaryStructureFlags(['helix']),
-        B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
-  helixalpha: {
-    '@desc': 'secondary structure-related.',
-    map: () => B.struct.generator.atomGroups({
-      'residue-test': B.core.flags.hasAny([
-        B.struct.type.secondaryStructureFlags(['alpha']),
-        B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
-  helix310: {
-    '@desc': 'secondary structure-related.',
-    map: () => B.struct.generator.atomGroups({
-      'residue-test': B.core.flags.hasAny([
-        B.struct.type.secondaryStructureFlags(['3-10']),
-        B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
-  helixpi: {
-    '@desc': 'secondary structure-related.',
-    map: () => B.struct.generator.atomGroups({
-      'residue-test': B.core.flags.hasAny([
-        B.struct.type.secondaryStructureFlags(['pi']),
-        B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
-  hetero: {
-    '@desc': 'PDB atoms designated as HETATM',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.ammp('isHet')
-    })
-  },
-  hydrophobic: {
-    '@desc': 'ALA GLY ILE LEU MET PHE PRO TRP TYR VAL',
-    map: () => h.resnameExpr(ResDict.hydrophobic)
-  },
-  large: {
-    '@desc': 'ARG GLU GLN HIS ILE LEU LYS MET PHE TRP TYR',
-    map: () => h.resnameExpr(ResDict.large)
-  },
-  medium: {
-    '@desc': 'ASN ASP CYS PRO THR VAL',
-    map: () => h.resnameExpr(ResDict.medium)
-  },
-  negative: {
-    '@desc': 'same as acidic -- ASP GLU',
-    map: () => h.resnameExpr(ResDict.acidic)
-  },
-  neutral: {
-    '@desc': 'amino and not (acidic or basic)',
-    map: () => B.struct.modifier.intersectBy({
-      0: h.resnameExpr(ResDict.amino),
-      by: h.invertExpr(h.resnameExpr(ResDict.acidic.concat(ResDict.basic)))
-    })
-  },
-  polar: {
-    '@desc': 'amino and not hydrophobic',
-    map: () => B.struct.modifier.intersectBy({
-      0: h.resnameExpr(ResDict.amino),
-      by: h.invertExpr(h.resnameExpr(ResDict.hydrophobic))
-    })
-  },
-  positive: {
-    '@desc': 'same as basic -- ARG HIS LYS',
-    map: () => h.resnameExpr(ResDict.basic)
-  },
-  sheet: {
-    '@desc': 'secondary structure-related',
-    map: () => B.struct.generator.atomGroups({
-      'residue-test': B.core.flags.hasAny([
-        B.struct.type.secondaryStructureFlags(['sheet']),
-        B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
-  small: {
-    '@desc': 'ALA GLY SER',
-    map: () => h.resnameExpr(ResDict.small)
-  },
-  surface: {
-    '@desc': 'amino and not buried',
-    map: () => B.struct.modifier.intersectBy({
-      0: h.resnameExpr(ResDict.amino),
-      by: h.invertExpr(h.resnameExpr(ResDict.buried))
-    })
-  },
-  turn: {
-    '@desc': 'secondary structure-related',
-    map: () => B.struct.generator.atomGroups({
-      'residue-test': B.core.flags.hasAny([
-        B.struct.type.secondaryStructureFlags(['turn']),
-        B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
-  alpha: {
-    '@desc': '(*.CA)',
-    map: () => B.struct.generator.atomGroups({
-      'atom-test': B.core.rel.eq([
-        B.atomName('CA'),
-        B.ammp('label_atom_id')
-      ])
-    })
-  },
-  base: {
-    '@desc': '(nucleic bases)'
-  },
-  backbone: {
-    '@desc': '(*.C, *.CA, *.N, and all nucleic other than the bases themselves)',
-    abbr: ['mainchain']
-  },
-  sidechain: {
-    '@desc': '((protein or nucleic) and not backbone)'
-  },
-  spine: {
-    '@desc': '(*.CA, *.N, *.C for proteins; *.P, *.O3\', *.O5\', *.C3\', *.C4\', *.C5 for nucleic acids)'
-  },
-  leadatom: {
-    '@desc': '(*.CA, *.P, and terminal *.O5\')'
-  },
-  solvent: {
-    '@desc': 'PDB "HOH", water, also the connected set of H-O-H in any model'
-  },
-}
+    },
+    protein: {
+        '@desc': 'defined as a group that (a) has one of the following group names: ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, ASX, GLX, or UNK; or (b) contains PDB atom designations [C, O, CA, and N] bonded correctly; or (c) does not contain "O" but contains [C, CA, and N] bonded correctly; or (d) has only one atom, which has name CA and does not have the group name CA (indicating a calcium atom).'
+    },
+    acidic: {
+        '@desc': 'ASP GLU',
+        map: () => h.resnameExpr(ResDict.acidic)
+    },
+    acyclic: {
+        '@desc': 'amino and not cyclic',
+        map: () => B.struct.modifier.intersectBy({
+            0: h.resnameExpr(ResDict.amino),
+            by: h.invertExpr(h.resnameExpr(ResDict.cyclic))
+        })
+    },
+    aliphatic: {
+        '@desc': 'ALA GLY ILE LEU VAL',
+        map: () => h.resnameExpr(ResDict.aliphatic)
+    },
+    amino: {
+        '@desc': 'all twenty standard amino acids, plus ASX, GLX, UNK',
+        map: () => h.resnameExpr(ResDict.amino)
+    },
+    aromatic: {
+        '@desc': 'HIS PHE TRP TYR (see also "isaromatic" for aromatic bonds)',
+        map: () => h.resnameExpr(ResDict.aromatic)
+    },
+    basic: {
+        '@desc': 'ARG HIS LYS',
+        map: () => h.resnameExpr(ResDict.basic)
+    },
+    buried: {
+        '@desc': 'ALA CYS ILE LEU MET PHE TRP VAL',
+        map: () => h.resnameExpr(ResDict.buried)
+    },
+    charged: {
+        '@desc': 'same as acidic or basic -- ASP GLU, ARG HIS LYS',
+        map: () => h.resnameExpr(ResDict.acidic.concat(ResDict.basic))
+    },
+    cyclic: {
+        '@desc': 'HIS PHE PRO TRP TYR',
+        map: () => h.resnameExpr(ResDict.cyclic)
+    },
+    helix: {
+        '@desc': 'secondary structure-related.',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['helix']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
+    helixalpha: {
+        '@desc': 'secondary structure-related.',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['alpha']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
+    helix310: {
+        '@desc': 'secondary structure-related.',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['3-10']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
+    helixpi: {
+        '@desc': 'secondary structure-related.',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['pi']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
+    hetero: {
+        '@desc': 'PDB atoms designated as HETATM',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.ammp('isHet')
+        })
+    },
+    hydrophobic: {
+        '@desc': 'ALA GLY ILE LEU MET PHE PRO TRP TYR VAL',
+        map: () => h.resnameExpr(ResDict.hydrophobic)
+    },
+    large: {
+        '@desc': 'ARG GLU GLN HIS ILE LEU LYS MET PHE TRP TYR',
+        map: () => h.resnameExpr(ResDict.large)
+    },
+    medium: {
+        '@desc': 'ASN ASP CYS PRO THR VAL',
+        map: () => h.resnameExpr(ResDict.medium)
+    },
+    negative: {
+        '@desc': 'same as acidic -- ASP GLU',
+        map: () => h.resnameExpr(ResDict.acidic)
+    },
+    neutral: {
+        '@desc': 'amino and not (acidic or basic)',
+        map: () => B.struct.modifier.intersectBy({
+            0: h.resnameExpr(ResDict.amino),
+            by: h.invertExpr(h.resnameExpr(ResDict.acidic.concat(ResDict.basic)))
+        })
+    },
+    polar: {
+        '@desc': 'amino and not hydrophobic',
+        map: () => B.struct.modifier.intersectBy({
+            0: h.resnameExpr(ResDict.amino),
+            by: h.invertExpr(h.resnameExpr(ResDict.hydrophobic))
+        })
+    },
+    positive: {
+        '@desc': 'same as basic -- ARG HIS LYS',
+        map: () => h.resnameExpr(ResDict.basic)
+    },
+    sheet: {
+        '@desc': 'secondary structure-related',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['sheet']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
+    small: {
+        '@desc': 'ALA GLY SER',
+        map: () => h.resnameExpr(ResDict.small)
+    },
+    surface: {
+        '@desc': 'amino and not buried',
+        map: () => B.struct.modifier.intersectBy({
+            0: h.resnameExpr(ResDict.amino),
+            by: h.invertExpr(h.resnameExpr(ResDict.buried))
+        })
+    },
+    turn: {
+        '@desc': 'secondary structure-related',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['turn']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
+    alpha: {
+        '@desc': '(*.CA)',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.rel.eq([
+                B.atomName('CA'),
+                B.ammp('label_atom_id')
+            ])
+        })
+    },
+    base: {
+        '@desc': '(nucleic bases)'
+    },
+    backbone: {
+        '@desc': '(*.C, *.CA, *.N, and all nucleic other than the bases themselves)',
+        abbr: ['mainchain']
+    },
+    sidechain: {
+        '@desc': '((protein or nucleic) and not backbone)'
+    },
+    spine: {
+        '@desc': '(*.CA, *.N, *.C for proteins; *.P, *.O3\', *.O5\', *.C3\', *.C4\', *.C5 for nucleic acids)'
+    },
+    leadatom: {
+        '@desc': '(*.CA, *.P, and terminal *.O5\')'
+    },
+    solvent: {
+        '@desc': 'PDB "HOH", water, also the connected set of H-O-H in any model'
+    },
+};
 
 

+ 30 - 30
src/mol-script/transpilers/jmol/markdown-docs.ts

@@ -1,9 +1,9 @@
-/* 
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
- * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                     
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com> 
- * 
- * @author Koya Sakuma 
+/*
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
+ *
+ * @author Koya Sakuma
  * This module was taken from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             */
 
 import { properties } from './properties';
@@ -11,53 +11,53 @@ import { operators } from './operators';
 import { keywords } from './keywords';
 
 
-const docs: string[] = [
+const _docs: string[] = [
     'Jmol',
     '============',
     '--------------------------------',
     ''
 ];
 
-docs.push(`## Properties\n\n`);
-docs.push('--------------------------------\n');
+_docs.push(`## Properties\n\n`);
+_docs.push('--------------------------------\n');
 for (const name in properties) {
-    if (properties[name].isUnsupported) continue
+    if (properties[name].isUnsupported) continue;
 
-    const names = [name]
-    if (properties[name].abbr) names.push(...properties[name].abbr!)
-    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+    const names = [name];
+    if (properties[name].abbr) names.push(...properties[name].abbr!);
+    _docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
 
     if (properties[name]['@desc']) {
-        docs.push(`*${properties[name]['@desc']}*\n`);
+        _docs.push(`*${properties[name]['@desc']}*\n`);
     }
 }
 
-docs.push(`## Operators\n\n`);
-docs.push('--------------------------------\n');
+_docs.push(`## Operators\n\n`);
+_docs.push('--------------------------------\n');
 operators.forEach(o => {
-    if (o.isUnsupported) return
+    if (o.isUnsupported) return;
 
-    const names = [o.name]
-    if (o.abbr) names.push(...o.abbr!)
-    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+    const names = [o.name];
+    if (o.abbr) names.push(...o.abbr!);
+    _docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
 
     if (o['@desc']) {
-        docs.push(`*${o['@desc']}*\n`);
+        _docs.push(`*${o['@desc']}*\n`);
     }
-})
+});
 
-docs.push(`## Keywords\n\n`);
-docs.push('--------------------------------\n');
+_docs.push(`## Keywords\n\n`);
+_docs.push('--------------------------------\n');
 for (const name in keywords) {
-    if (!keywords[name].map) continue
+    if (!keywords[name].map) continue;
 
-    const names = [name]
-    if (keywords[name].abbr) names.push(...keywords[name].abbr!)
-    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+    const names = [name];
+    if (keywords[name].abbr) names.push(...keywords[name].abbr!);
+    _docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
 
     if (keywords[name]['@desc']) {
-        docs.push(`*${keywords[name]['@desc']}*\n`);
+        _docs.push(`*${keywords[name]['@desc']}*\n`);
     }
 }
 
-export default docs.join('\n')
+export const docs = _docs.join('\n');

+ 32 - 32
src/mol-script/transpilers/jmol/operators.ts

@@ -1,9 +1,9 @@
-/*                                                                                                                                           
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
- * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                     
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                 
- *                                                                                                                                           
- * @author Koya Sakuma                                                                                                                       
+/*
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
+ *
+ * @author Koya Sakuma
  * This module was taken from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             \
  */
 
@@ -13,33 +13,33 @@ import * as h from '../helper';
 import { MolScriptBuilder } from '../../../mol-script/language/builder';
 const B = MolScriptBuilder;
 import { OperatorList } from '../types';
-//import { Expression } from '../../language/expression';
+// import { Expression } from '../../language/expression';
 
 
 export const operators: OperatorList = [
-  {
-    '@desc': 'Selects atoms that are not included in s1.',
-    '@examples': ['not ARG'],
-    name: 'not',
-    type: h.prefix,
-    rule: P.MonadicParser.alt(P.MonadicParser.regex(/NOT/i).skip(P.MonadicParser.whitespace), P.MonadicParser.string('!').skip(P.MonadicParser.optWhitespace)),
-    map: (op, selection) => h.invertExpr(selection),
-  },
-  {
-    '@desc': 'Selects atoms included in both s1 and s2.',
-    '@examples': ['ASP and .CA'],
-    name: 'and',
-    type: h.binaryLeft,
-    rule: h.infixOp(/AND|&/i),
-    map: (op, selection, by) => B.struct.modifier.intersectBy({ 0: selection, by })
-  },
-  {
-    '@desc': 'Selects atoms included in either s1 or s2.',
-    '@examples': ['ASP or GLU'],
-    name: 'or',
-    type: h.binaryLeft,
-    rule: h.infixOp(/OR|\|/i),
-    map: (op, s1, s2) => B.struct.combinator.merge([s1, s2])
-  }
-]
+    {
+        '@desc': 'Selects atoms that are not included in s1.',
+        '@examples': ['not ARG'],
+        name: 'not',
+        type: h.prefix,
+        rule: P.MonadicParser.alt(P.MonadicParser.regex(/NOT/i).skip(P.MonadicParser.whitespace), P.MonadicParser.string('!').skip(P.MonadicParser.optWhitespace)),
+        map: (op, selection) => h.invertExpr(selection),
+    },
+    {
+        '@desc': 'Selects atoms included in both s1 and s2.',
+        '@examples': ['ASP and .CA'],
+        name: 'and',
+        type: h.binaryLeft,
+        rule: h.infixOp(/AND|&/i),
+        map: (op, selection, by) => B.struct.modifier.intersectBy({ 0: selection, by })
+    },
+    {
+        '@desc': 'Selects atoms included in either s1 or s2.',
+        '@examples': ['ASP or GLU'],
+        name: 'or',
+        type: h.binaryLeft,
+        rule: h.infixOp(/OR|\|/i),
+        map: (op, s1, s2) => B.struct.combinator.merge([s1, s2])
+    }
+];
 

+ 221 - 222
src/mol-script/transpilers/jmol/parser.ts

@@ -1,8 +1,8 @@
 /**
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                
- *                                                                                                                                          
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
+ *
  * @author Koya Sakuma
  * This module was taken from MolQL and modified in similar manner as pymol and vmd tranpilers.                                              **/
 
@@ -18,239 +18,238 @@ import { AtomGroupArgs } from '../types';
 import { Transpiler } from '../transpiler';
 import { OperatorList } from '../types';
 
-//const propertiesDict = h.getPropertyRules(properties);
+// const propertiesDict = h.getPropertyRules(properties);
 
-//const slash = P.MonadicParser.string('/');
+// const slash = P.MonadicParser.string('/');
 
 
 // <, <=, =, >=, >, !=, and LIKE
 const valueOperators: OperatorList = [
-  {
-    '@desc': 'value comparisons',
-    '@examples': [],
-    name: '=',
-    abbr: ['=='],
-    type: h.binaryLeft,
-    rule: P.MonadicParser.regexp(/\s*(LIKE|>=|<=|=|!=|>|<)\s*/i, 1),
-    map: (op, e1, e2) => {
-      // console.log(op, e1, e2)
-      let expr
-      if (e1 === 'structure') {
-        expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e2)])
-      } else if (e2 === 'structure') {
-        expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e1)])
-      } else if (e1.head === 'core.type.regex') {
-        expr = B.core.str.match([ e1, B.core.type.str([e2]) ])
-      } else if (e2.head === 'core.type.regex') {
-        expr = B.core.str.match([ e2, B.core.type.str([e1]) ])
-      } else if (op.toUpperCase() === 'LIKE') {
-        if (e1.head) {
-          expr = B.core.str.match([
-            B.core.type.regex([`^${e2}$`, 'i']),
-            B.core.type.str([e1])
-          ])
-        } else {
-          expr = B.core.str.match([
-            B.core.type.regex([`^${e1}$`, 'i']),
-            B.core.type.str([e2])
-          ])
+    {
+        '@desc': 'value comparisons',
+        '@examples': [],
+        name: '=',
+        abbr: ['=='],
+        type: h.binaryLeft,
+        rule: P.MonadicParser.regexp(/\s*(LIKE|>=|<=|=|!=|>|<)\s*/i, 1),
+        map: (op, e1, e2) => {
+            // console.log(op, e1, e2)
+            let expr;
+            if (e1 === 'structure') {
+                expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e2)]);
+            } else if (e2 === 'structure') {
+                expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e1)]);
+            } else if (e1.head === 'core.type.regex') {
+                expr = B.core.str.match([e1, B.core.type.str([e2])]);
+            } else if (e2.head === 'core.type.regex') {
+                expr = B.core.str.match([e2, B.core.type.str([e1])]);
+            } else if (op.toUpperCase() === 'LIKE') {
+                if (e1.head) {
+                    expr = B.core.str.match([
+                        B.core.type.regex([`^${e2}$`, 'i']),
+                        B.core.type.str([e1])
+                    ]);
+                } else {
+                    expr = B.core.str.match([
+                        B.core.type.regex([`^${e1}$`, 'i']),
+                        B.core.type.str([e2])
+                    ]);
+                }
+            }
+            if (!expr) {
+                if (e1.head) e2 = h.wrapValue(e1, e2);
+                if (e2.head) e1 = h.wrapValue(e2, e1);
+                switch (op) {
+                    case '=':
+                        expr = B.core.rel.eq([e1, e2]);
+                        break;
+                    case '!=':
+                        expr = B.core.rel.neq([e1, e2]);
+                        break;
+                    case '>':
+                        expr = B.core.rel.gr([e1, e2]);
+                        break;
+                    case '<':
+                        expr = B.core.rel.lt([e1, e2]);
+                        break;
+                    case '>=':
+                        expr = B.core.rel.gre([e1, e2]);
+                        break;
+                    case '<=':
+                        expr = B.core.rel.lte([e1, e2]);
+                        break;
+                    default: throw new Error(`value operator '${op}' not supported`);
+                }
+            }
+            return B.struct.generator.atomGroups({ 'atom-test': expr });
         }
-      }
-      if (!expr) {
-        if (e1.head) e2 = h.wrapValue(e1, e2)
-        if (e2.head) e1 = h.wrapValue(e2, e1)
-        switch (op) {
-          case '=':
-            expr = B.core.rel.eq([e1, e2])
-            break
-          case '!=':
-            expr = B.core.rel.neq([e1, e2])
-            break
-          case '>':
-            expr = B.core.rel.gr([e1, e2])
-            break
-          case '<':
-            expr = B.core.rel.lt([e1, e2])
-            break
-          case '>=':
-            expr = B.core.rel.gre([e1, e2])
-            break
-          case '<=':
-            expr = B.core.rel.lte([e1, e2])
-            break
-          default: throw new Error(`value operator '${op}' not supported`);
-        }
-      }
-      return B.struct.generator.atomGroups({ 'atom-test': expr })
     }
-  }
-]
+];
 
-function atomExpressionQuery (x: any[]) {
-  const [resno, inscode, chainname, atomname, altloc, ] = x[1]
-  const tests: AtomGroupArgs = {}
+function atomExpressionQuery(x: any[]) {
+    const [resno, inscode, chainname, atomname, altloc] = x[1];
+    const tests: AtomGroupArgs = {};
 
-  if (chainname) {
+    if (chainname) {
     // should be configurable, there is an option in Jmol to use auth or label
-    tests['chain-test'] = B.core.rel.eq([ B.ammp('auth_asym_id'), chainname ])
-  }
+        tests['chain-test'] = B.core.rel.eq([B.ammp('auth_asym_id'), chainname]);
+    }
 
-  const resProps = []
-  if (resno) resProps.push(B.core.rel.eq([ B.ammp('auth_seq_id'), resno ]))
-  if (inscode) resProps.push(B.core.rel.eq([ B.ammp('pdbx_PDB_ins_code'), inscode ]))
-  if (resProps.length) tests['residue-test'] = h.andExpr(resProps)
+    const resProps = [];
+    if (resno) resProps.push(B.core.rel.eq([B.ammp('auth_seq_id'), resno]));
+    if (inscode) resProps.push(B.core.rel.eq([B.ammp('pdbx_PDB_ins_code'), inscode]));
+    if (resProps.length) tests['residue-test'] = h.andExpr(resProps);
 
-  const atomProps = []
-  if (atomname) atomProps.push(B.core.rel.eq([ B.ammp('auth_atom_id'), atomname ]))
-  if (altloc) atomProps.push(B.core.rel.eq([ B.ammp('label_alt_id'), altloc ]))
-  if (atomProps.length) tests['atom-test'] = h.andExpr(atomProps)
+    const atomProps = [];
+    if (atomname) atomProps.push(B.core.rel.eq([B.ammp('auth_atom_id'), atomname]));
+    if (altloc) atomProps.push(B.core.rel.eq([B.ammp('label_alt_id'), altloc]));
+    if (atomProps.length) tests['atom-test'] = h.andExpr(atomProps);
 
-  return B.struct.generator.atomGroups(tests)
+    return B.struct.generator.atomGroups(tests);
 }
 
 const lang = P.MonadicParser.createLanguage({
-  Integer: () => P.MonadicParser.regexp(/-?[0-9]+/).map(Number).desc('integer'),
-
-    Parens: function (r:any) {
-    return P.MonadicParser.alt(
-      r.Parens,
-      r.Operator,
-      r.Expression
-    ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'))
-  },
-
-    Expression: function(r:any) {
-    return P.MonadicParser.alt(
-      r.Keywords,
-
-	r.Resno.lookahead(P.MonadicParser.regexp(/\s*(?!(LIKE|>=|<=|!=|[:^%/.=><]))/i)).map((x:any) => B.struct.generator.atomGroups({
-          'residue-test': B.core.rel.eq([ B.ammp('auth_seq_id'), x ])
-      })),
-      r.AtomExpression.map(atomExpressionQuery),
-
-      r.ValueQuery,
-
-      r.Element.map((x: string) => B.struct.generator.atomGroups({
-        'atom-test': B.core.rel.eq([ B.acp('elementSymbol'), B.struct.type.elementSymbol(x) ])
-      })),
-      r.Resname.map((x: string) => B.struct.generator.atomGroups({
-        'residue-test': B.core.rel.eq([ B.ammp('label_comp_id'), x ])
-      })),
-    )
-  },
-
-Operator: function(r:any) {
-    return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression))
-  },
-
-AtomExpression: function(r:any) {
-    return P.MonadicParser.seq(
-      P.MonadicParser.lookahead(r.AtomPrefix),
-      P.MonadicParser.seq(
-        r.Resno.or(P.MonadicParser.of(null)),
-        r.Inscode.or(P.MonadicParser.of(null)),
-        r.Chainname.or(P.MonadicParser.of(null)),
-        r.Atomname.or(P.MonadicParser.of(null)),
-        r.Altloc.or(P.MonadicParser.of(null)),
-        r.Model.or(P.MonadicParser.of(null))
-      )
-    )
-  },
-
-  AtomPrefix: () => P.MonadicParser.regexp(/[0-9:^%/.]/).desc('atom-prefix'),
-
-  Chainname: () => P.MonadicParser.regexp(/:([A-Za-z]{1,3})/, 1).desc('chainname'),
-  Model: () => P.MonadicParser.regexp(/\/([0-9]+)/, 1).map(Number).desc('model'),
-  Element: () => P.MonadicParser.regexp(/_([A-Za-z]{1,3})/, 1).desc('element'),
-  Atomname: () => P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1).map(B.atomName).desc('atomname'),
-  Resname: () => P.MonadicParser.regexp(/[a-zA-Z0-9]{1,4}/).desc('resname'),
-Resno: (r:any) => r.Integer.desc('resno'),
-  Altloc: () => P.MonadicParser.regexp(/%([a-zA-Z0-9])/, 1).desc('altloc'),
-  Inscode: () => P.MonadicParser.regexp(/\^([a-zA-Z0-9])/, 1).desc('inscode'),
-
-  // BracketedResname: function (r) {
-  //   return P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1)
-  //     .desc('bracketed-resname')
-  //   // [0SD]
-  // },
-
-  // ResnoRange: function (r) {
-  //   return P.MonadicParser.regexp(/\.([\s]){1,3}/, 1)
-  //     .desc('resno-range')
-  //   // 123-200
-  //   // -12--3
-  // },
-
-  Keywords: () => P.MonadicParser.alt(...h.getKeywordRules(keywords)),
-
-Query: function(r:any) {
-    return P.MonadicParser.alt(
-      r.Operator,
-      r.Parens,
-      r.Expression
-    ).trim(P.MonadicParser.optWhitespace)
-  },
-
-  Number: function () {
-    return P.MonadicParser.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/)
-      .map(Number)
-      .desc('number')
-  },
-
-  String: function () {
-    const w = h.getReservedWords(properties, keywords, operators)
-      .sort(h.strLenSortFn).map(h.escapeRegExp).join('|')
-    return P.MonadicParser.alt(
-      P.MonadicParser.regexp(new RegExp(`(?!(${w}))[A-Z0-9_]+`, 'i')),
-      P.MonadicParser.regexp(/'((?:[^"\\]|\\.)*)'/, 1),
-      P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map(x => B.core.type.regex([`^${x}$`, 'i']))
-    )
-  },
-
-Value: function (r:any) {
-    return P.MonadicParser.alt(r.Number, r.String)
-  },
-
-ValueParens: function (r:any) {
-    return P.MonadicParser.alt(
-      r.ValueParens,
-      r.ValueOperator,
-      r.ValueExpressions
-    ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'))
-  },
-
-  ValuePropertyNames: function() {
-    return P.MonadicParser.alt(...h.getPropertyNameRules(properties, /LIKE|>=|<=|=|!=|>|<|\)|\s/i))
-  },
-
-ValueOperator: function(r:any) {
-    return h.combineOperators(valueOperators, P.MonadicParser.alt(r.ValueParens, r.ValueExpressions))
-  },
-
-ValueExpressions: function(r:any) {
-    return P.MonadicParser.alt(
-      r.Value,
-      r.ValuePropertyNames
-    )
-  },
-
-ValueQuery: function(r:any) {
-    return P.MonadicParser.alt(
-	r.ValueOperator.map((x:any) => {
-        if (x.head) {
-          if (x.head.startsWith('structure-query.generator')) return x
-        } else {
-          if (typeof x === 'string' && x.length <= 4) {
-            return B.struct.generator.atomGroups({
-              'residue-test': B.core.rel.eq([ B.ammp('label_comp_id'), x ])
+    Integer: () => P.MonadicParser.regexp(/-?[0-9]+/).map(Number).desc('integer'),
+
+    Parens: function (r: any) {
+        return P.MonadicParser.alt(
+            r.Parens,
+            r.Operator,
+            r.Expression
+        ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
+    },
+
+    Expression: function (r: any) {
+        return P.MonadicParser.alt(
+            r.Keywords,
+
+            r.Resno.lookahead(P.MonadicParser.regexp(/\s*(?!(LIKE|>=|<=|!=|[:^%/.=><]))/i)).map((x: any) => B.struct.generator.atomGroups({
+                'residue-test': B.core.rel.eq([B.ammp('auth_seq_id'), x])
+            })),
+            r.AtomExpression.map(atomExpressionQuery),
+
+            r.ValueQuery,
+
+            r.Element.map((x: string) => B.struct.generator.atomGroups({
+                'atom-test': B.core.rel.eq([B.acp('elementSymbol'), B.struct.type.elementSymbol(x)])
+            })),
+            r.Resname.map((x: string) => B.struct.generator.atomGroups({
+                'residue-test': B.core.rel.eq([B.ammp('label_comp_id'), x])
+            })),
+        );
+    },
+
+    Operator: function (r: any) {
+        return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression));
+    },
+
+    AtomExpression: function (r: any) {
+        return P.MonadicParser.seq(
+            P.MonadicParser.lookahead(r.AtomPrefix),
+            P.MonadicParser.seq(
+                r.Resno.or(P.MonadicParser.of(null)),
+                r.Inscode.or(P.MonadicParser.of(null)),
+                r.Chainname.or(P.MonadicParser.of(null)),
+                r.Atomname.or(P.MonadicParser.of(null)),
+                r.Altloc.or(P.MonadicParser.of(null)),
+                r.Model.or(P.MonadicParser.of(null))
+            )
+        );
+    },
+
+    AtomPrefix: () => P.MonadicParser.regexp(/[0-9:^%/.]/).desc('atom-prefix'),
+
+    Chainname: () => P.MonadicParser.regexp(/:([A-Za-z]{1,3})/, 1).desc('chainname'),
+    Model: () => P.MonadicParser.regexp(/\/([0-9]+)/, 1).map(Number).desc('model'),
+    Element: () => P.MonadicParser.regexp(/_([A-Za-z]{1,3})/, 1).desc('element'),
+    Atomname: () => P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1).map(B.atomName).desc('atomname'),
+    Resname: () => P.MonadicParser.regexp(/[a-zA-Z0-9]{1,4}/).desc('resname'),
+    Resno: (r: any) => r.Integer.desc('resno'),
+    Altloc: () => P.MonadicParser.regexp(/%([a-zA-Z0-9])/, 1).desc('altloc'),
+    Inscode: () => P.MonadicParser.regexp(/\^([a-zA-Z0-9])/, 1).desc('inscode'),
+
+    // BracketedResname: function (r) {
+    //   return P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1)
+    //     .desc('bracketed-resname')
+    //   // [0SD]
+    // },
+
+    // ResnoRange: function (r) {
+    //   return P.MonadicParser.regexp(/\.([\s]){1,3}/, 1)
+    //     .desc('resno-range')
+    //   // 123-200
+    //   // -12--3
+    // },
+
+    Keywords: () => P.MonadicParser.alt(...h.getKeywordRules(keywords)),
+
+    Query: function (r: any) {
+        return P.MonadicParser.alt(
+            r.Operator,
+            r.Parens,
+            r.Expression
+        ).trim(P.MonadicParser.optWhitespace);
+    },
+
+    Number: function () {
+        return P.MonadicParser.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/)
+            .map(Number)
+            .desc('number');
+    },
+
+    String: function () {
+        const w = h.getReservedWords(properties, keywords, operators)
+            .sort(h.strLenSortFn).map(h.escapeRegExp).join('|');
+        return P.MonadicParser.alt(
+            P.MonadicParser.regexp(new RegExp(`(?!(${w}))[A-Z0-9_]+`, 'i')),
+            P.MonadicParser.regexp(/'((?:[^"\\]|\\.)*)'/, 1),
+            P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map(x => B.core.type.regex([`^${x}$`, 'i']))
+        );
+    },
+
+    Value: function (r: any) {
+        return P.MonadicParser.alt(r.Number, r.String);
+    },
+
+    ValueParens: function (r: any) {
+        return P.MonadicParser.alt(
+            r.ValueParens,
+            r.ValueOperator,
+            r.ValueExpressions
+        ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
+    },
+
+    ValuePropertyNames: function () {
+        return P.MonadicParser.alt(...h.getPropertyNameRules(properties, /LIKE|>=|<=|=|!=|>|<|\)|\s/i));
+    },
+
+    ValueOperator: function (r: any) {
+        return h.combineOperators(valueOperators, P.MonadicParser.alt(r.ValueParens, r.ValueExpressions));
+    },
+
+    ValueExpressions: function (r: any) {
+        return P.MonadicParser.alt(
+            r.Value,
+            r.ValuePropertyNames
+        );
+    },
+
+    ValueQuery: function (r: any) {
+        return P.MonadicParser.alt(
+            r.ValueOperator.map((x: any) => {
+                if (x.head) {
+                    if (x.head.startsWith('structure-query.generator')) return x;
+                } else {
+                    if (typeof x === 'string' && x.length <= 4) {
+                        return B.struct.generator.atomGroups({
+                            'residue-test': B.core.rel.eq([B.ammp('label_comp_id'), x])
+                        });
+                    }
+                }
+                throw new Error(`values must be part of an comparison, value '${x}'`);
             })
-          }
-        }
-        throw new Error(`values must be part of an comparison, value '${x}'`)
-      })
-    )
-  }
-})
-
-const transpiler: Transpiler = str => lang.Query.tryParse(str)
-export default transpiler
+        );
+    }
+});
+
+export const transpiler: Transpiler = str => lang.Query.tryParse(str);

File diff suppressed because it is too large
+ 37 - 539
src/mol-script/transpilers/jmol/properties.ts


+ 20 - 21
src/mol-script/transpilers/jmol/symbols.ts

@@ -1,9 +1,9 @@
-/*                                                                                                                                           
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
- * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                     
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                 
- *                                                                                                                                           
- * @author Koya Sakuma                                                                                                                       
+/*
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
+ *
+ * @author Koya Sakuma
  * This module was taken from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             \
 */
 
@@ -11,26 +11,25 @@ import { properties } from './properties';
 import { operators } from './operators';
 import { keywords } from './keywords';
 
-export const Properties: string[] = []
+export const Properties: string[] = [];
 for (const name in properties) {
-    if (properties[name].isUnsupported) continue
-    Properties.push(name)
-    if (properties[name].abbr) Properties.push(...properties[name].abbr!)
+    if (properties[name].isUnsupported) continue;
+    Properties.push(name);
+    if (properties[name].abbr) Properties.push(...properties[name].abbr!);
 }
 
-export const Operators: string[] = []
+export const Operators: string[] = [];
 operators.forEach(o => {
-    if (o.isUnsupported) return
-    Operators.push(o.name)
-    if (o.abbr) Operators.push(...o.abbr)
-})
+    if (o.isUnsupported) return;
+    Operators.push(o.name);
+    if (o.abbr) Operators.push(...o.abbr);
+});
 
-export const Keywords: string[] = []
+export const Keywords: string[] = [];
 for (const name in keywords) {
-    if (!keywords[name].map) continue
-    Keywords.push(name)
-    if (keywords[name].abbr) Keywords.push(...keywords[name].abbr!)
+    if (!keywords[name].map) continue;
+    Keywords.push(name);
+    if (keywords[name].abbr) Keywords.push(...keywords[name].abbr!);
 }
 
-const _all = { Properties, Operators, Keywords }
-export default _all
+export const _all = { Properties, Operators, Keywords };

+ 8 - 8
src/mol-script/transpilers/pymol/keywords.ts

@@ -205,28 +205,28 @@ export const keywords: KeywordDict = {
         map: () => B.struct.generator.atomGroups({
             'atom-test': B.core.set.has([
                 B.core.type.set(Backbone.protein.concat(ResDict.protein)),
-		B.ammp('label_atom_id')	
+                B.ammp('label_atom_id')
 	    ])
-	}),
-    },	    
+        }),
+    },
     proteinxxxxxx: {
         '@desc': 'protein................',
-	abbr: ['polymer.protein'],
+        abbr: ['polymer.protein'],
         map: () => B.struct.generator.atomGroups({
             'residue-test': B.core.set.has([
                 B.core.type.set(ResDict.protein),
                 B.ammp('label_comp_id')
             ])
-	})
+        })
     },
     nucleicxxxxx: {
-	'@desc': 'protein................',
-	abbr: ['polymer.nucleic'],
+        '@desc': 'protein................',
+        abbr: ['polymer.nucleic'],
         map: () => B.struct.generator.atomGroups({
             'residue-test': B.core.set.has([
                 B.core.type.set(ResDict.nucleic),
                 B.ammp('label_comp_id')
             ])
         })
-    }				   
+    }
 };

+ 4 - 4
src/mol-script/transpilers/pymol/operators.ts

@@ -92,7 +92,7 @@ export const operators: OperatorList = [
         type: h.postfix,
         rule: h
             .postfixOp(/GAP\s+([-+]?[0-9]*\.?[0-9]+)/i, 1)
-            .map((x:any) => parseFloat(x)),
+            .map((x: any) => parseFloat(x)),
         map: (distance: number, target: Expression) => {
             return B.struct.filter.within({
                 '0': B.struct.generator.atomGroups(),
@@ -112,7 +112,7 @@ export const operators: OperatorList = [
         type: h.postfix,
         rule: h
             .postfixOp(/(AROUND|a\.)\s+([-+]?[0-9]*\.?[0-9]+)/i, 2)
-            .map((x:any) => parseFloat(x)),
+            .map((x: any) => parseFloat(x)),
         map: (radius: number, target: Expression) => {
             return B.struct.modifier.exceptBy({
                 '0': B.struct.filter.within({
@@ -133,7 +133,7 @@ export const operators: OperatorList = [
         type: h.postfix,
         rule: h
             .postfixOp(/(EXPAND|x\.)\s+([-+]?[0-9]*\.?[0-9]+)/i, 2)
-            .map((x:any) => parseFloat(x)),
+            .map((x: any) => parseFloat(x)),
         map: (radius: number, selection: Expression) => {
             return B.struct.modifier.includeSurroundings({ 0: selection, radius });
         },
@@ -353,7 +353,7 @@ export const operators: OperatorList = [
         name: 'extend',
         abbr: ['xt.'],
         type: h.postfix,
-        rule: h.postfixOp(/(EXTEND|xt\.)\s+([0-9]+)/i, 2).map((x:any) => parseInt(x)),
+        rule: h.postfixOp(/(EXTEND|xt\.)\s+([0-9]+)/i, 2).map((x: any) => parseInt(x)),
         map: (count: number, selection: Expression) => {
             return h.asAtoms(
                 B.struct.modifier.includeConnected({

+ 9 - 10
src/mol-script/transpilers/pymol/parser.ts

@@ -31,7 +31,7 @@ function atomSelectionQuery(x: any) {
     const tests: AtomGroupArgs = {};
     const props: { [k: string]: any[] } = {};
 
-    for (let k in x) {
+    for (const k in x) {
         const ps = properties[k];
         if (!ps) {
             throw new Error(`property '${k}' not supported, value '${x[k]}'`);
@@ -41,7 +41,7 @@ function atomSelectionQuery(x: any) {
         props[ps.level].push(x[k]);
     }
 
-    for (let p in props) {
+    for (const p in props) {
         tests[p] = h.andExpr(props[p]);
     }
 
@@ -49,7 +49,7 @@ function atomSelectionQuery(x: any) {
 }
 
 const lang = P.MonadicParser.createLanguage({
-    Parens: function (r : any) {
+    Parens: function (r: any) {
         return P.MonadicParser.alt(
             r.Parens,
             r.Operator,
@@ -57,7 +57,7 @@ const lang = P.MonadicParser.createLanguage({
         ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
     },
 
-    Expression: function (r : any) {
+    Expression: function (r: any) {
         return P.MonadicParser.alt(
 	    r.Keywords,
             r.AtomSelectionMacro.map(atomSelectionQuery),
@@ -68,7 +68,7 @@ const lang = P.MonadicParser.createLanguage({
         );
     },
 
-    AtomSelectionMacro: function (r : any) {
+    AtomSelectionMacro: function (r: any) {
         return P.MonadicParser.alt(
             slash.then(P.MonadicParser.alt(
                 P.MonadicParser.seq(
@@ -135,9 +135,9 @@ const lang = P.MonadicParser.createLanguage({
             .sort(h.strLenSortFn).map(h.escapeRegExp).join('|');
         return P.MonadicParser.regexp(new RegExp(`(?!(${w}))[A-Z0-9_]+`, 'i'));
     },
-    Object: (r : any) => {
+    Object: (r: any) => {
         return r.ObjectProperty.notFollowedBy(slash)
-            .map( (x:any)  => { throw new Error(`property 'object' not supported, value '${x}'`); });
+            .map((x: any) => { throw new Error(`property 'object' not supported, value '${x}'`); });
     },
 
     // Selects peptide sequence matching upper-case one-letter
@@ -155,11 +155,11 @@ const lang = P.MonadicParser.createLanguage({
             .map(h.makeError(`operator 'rep' not supported`));
     },
 
-    Operator: function (r : any) {
+    Operator: function (r: any) {
         return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression, r.Operator));
     },
 
-    Query: function (r : any) {
+    Query: function (r: any) {
         return P.MonadicParser.alt(
             r.Operator,
             r.Parens,
@@ -169,4 +169,3 @@ const lang = P.MonadicParser.createLanguage({
 });
 
 export const transpiler: Transpiler = str => lang.Query.tryParse(str);
-export default transpiler

+ 3 - 3
src/mol-script/transpilers/pymol/properties.ts

@@ -10,7 +10,7 @@ const B = MolScriptBuilder;
 import { PropertyDict } from '../types';
 
 const reFloat = /[-+]?[0-9]*\.?[0-9]+/;
-//const rePosInt = /[0-9]+/;
+// const rePosInt = /[0-9]+/;
 
 function atomNameListMap(x: string) { return x.split('+').map(B.atomName); }
 function listMap(x: string) { return x.split('+').map(x => x.replace(/^["']|["']$/g, '')); }
@@ -105,14 +105,14 @@ export const properties: PropertyDict = {
     id: {
         '@desc': 'external-index-number a single integer',
         '@examples': ['id 23'],
-	regex: /[0-9+-]+/, map: listOrRangeMap,
+        regex: /[0-9+-]+/, map: listOrRangeMap,
         level: 'atom-test', property: B.ammp('id')
     },
     index: {
         '@desc': 'internal-index-number a single integer',
         '@examples': ['index 11'],
         regex: /[0-9+-]+/, map: listOrRangeMap,
-        level: 'atom-test',property: B.ammp('id')
+        level: 'atom-test', property: B.ammp('id')
     },
     ss: {
         '@desc': 'secondary-structure-type list of single letters. Helical regions should be assigned H and sheet regions S. Loop regions can either be assigned L or be blank.',

+ 2 - 2
src/mol-script/transpilers/rasmol/examples.ts

@@ -6,7 +6,7 @@
  * @author Koya Sakuma
  */
 
-export default [{
+export const rasmolSelectionsExamples = [{
     name: 'Residue 50 or 135',
     value: '50 or 135'
 }, {
@@ -24,4 +24,4 @@ export default [{
 }, {
     name: 'Pyrimidine residues',
     value: 'pyrimidine'
-}]
+}];

+ 204 - 204
src/mol-script/transpilers/rasmol/keywords.ts

@@ -1,5 +1,5 @@
-/**                                                                                                                                        
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+/**
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                      * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                 *
  * @author Koya Sakuma                                                                                                                       * This module was based on jmol transpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.
 **/
@@ -17,49 +17,49 @@ const Backbone = {
 
 
 function nucleicExpr() {
-  return B.struct.combinator.merge([
-      B.struct.generator.atomGroups({
+    return B.struct.combinator.merge([
+        B.struct.generator.atomGroups({
 	  'residue-test': B.core.set.has([
-              B.set(...['G', 'C', 'A', 'T', 'U', 'I', 'DG', 'DC', 'DA', 'DT', 'DU', 'DI', '+G', '+C', '+A', '+T', '+U', '+I']),
-              B.ammp('label_comp_id')
+                B.set(...['G', 'C', 'A', 'T', 'U', 'I', 'DG', 'DC', 'DA', 'DT', 'DU', 'DI', '+G', '+C', '+A', '+T', '+U', '+I']),
+                B.ammp('label_comp_id')
 	  ])
-      }),
-      B.struct.filter.pick({
+        }),
+        B.struct.filter.pick({
 	  0: B.struct.generator.atomGroups({
-              'group-by': B.ammp('residueKey')
+                'group-by': B.ammp('residueKey')
 	  }),
 	  test: B.core.logic.and([
-              B.core.rel.eq([ B.struct.atomSet.atomCount(), 1 ]),
-              B.core.rel.eq([ B.ammp('label_atom_id'), B.atomName('P') ]),
+                B.core.rel.eq([B.struct.atomSet.atomCount(), 1]),
+                B.core.rel.eq([B.ammp('label_atom_id'), B.atomName('P')]),
 	  ])
-      }),
-      B.struct.filter.pick({
+        }),
+        B.struct.filter.pick({
 	  0: B.struct.generator.atomGroups({
-              'group-by': B.ammp('residueKey')
+                'group-by': B.ammp('residueKey')
 	  }),
 	  test: B.core.logic.or([
-              B.core.set.isSubset([
-		  h.atomNameSet([ "C1'", "C2'", "O3'", "C3'", "C4'", "C5'", "O5'" ]),
+                B.core.set.isSubset([
+		  h.atomNameSet(["C1'", "C2'", "O3'", "C3'", "C4'", "C5'", "O5'"]),
 		  B.ammpSet('label_atom_id')
-              ]),
-              B.core.set.isSubset([
-		  h.atomNameSet([ 'C1*', 'C2*', 'O3*', 'C3*', 'C4*', 'C5*', 'O5*' ]),
+                ]),
+                B.core.set.isSubset([
+		  h.atomNameSet(['C1*', 'C2*', 'O3*', 'C3*', 'C4*', 'C5*', 'O5*']),
 		  B.ammpSet('label_atom_id')
-              ])
+                ])
 	  ])
-      })
-  ])
+        })
+    ]);
 }
 
 
 
 const ResDict = {
     aliphatic: ['ALA', 'GLY', 'ILE', 'LEU', 'VAL'],
-    amino: ['ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL', 'ASX', 'GLX', 'UNK', ],
+    amino: ['ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE', 'LEU', 'LYS', 'MET', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL', 'ASX', 'GLX', 'UNK'],
     acidic: ['ASP', 'GLU'],
     aromatic: ['HIS', 'PHE', 'TRP', 'TYR'],
     basic: ['ARG', 'HIS', 'LYS'],
-    buried: ['ALA','CYS', 'ILE', 'LEU', 'MET', 'PHE', 'TRP', 'VAL'],
+    buried: ['ALA', 'CYS', 'ILE', 'LEU', 'MET', 'PHE', 'TRP', 'VAL'],
     cg: ['CYT', 'C', 'GUA', 'G'],
     cyclic: ['HIS', 'PHE', 'PRO', 'TRP', 'TYR'],
     hydrophobic: ['ALA', 'GLY', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'TYR', 'VAL'],
@@ -73,281 +73,281 @@ const ResDict = {
 
 
 export const keywords: KeywordDict = {
-  // general terms
-  all: {
-      '@desc': 'all atoms; same as *',
-      abbr: ['*'],
-      map: () => B.struct.generator.all()
-  },
+    // general terms
+    all: {
+        '@desc': 'all atoms; same as *',
+        abbr: ['*'],
+        map: () => B.struct.generator.all()
+    },
     none: {
-	'@desc': 'no atoms',
-	map: () => B.struct.generator.empty()
-  },
+        '@desc': 'no atoms',
+        map: () => B.struct.generator.empty()
+    },
     selected: {
-	'@desc': 'atoms that have been selected; defaults to all when a file is first loaded'
+        '@desc': 'atoms that have been selected; defaults to all when a file is first loaded'
     },
     unitcell: {
-	'@desc': 'atoms within the current unitcell, which may be offset. This includes atoms on the faces and at the vertices of the unitcell.'
+        '@desc': 'atoms within the current unitcell, which may be offset. This includes atoms on the faces and at the vertices of the unitcell.'
     },
     ions: {
-	'@desc': '(specifically the PDB designations "PO4" and "SO4")'
+        '@desc': '(specifically the PDB designations "PO4" and "SO4")'
     },
     ligand: {
-	'@desc': '(originally "hetero and not solvent"; changed to "!(protein,nucleic,water,UREA)" for Jmol 12.2)'
+        '@desc': '(originally "hetero and not solvent"; changed to "!(protein,nucleic,water,UREA)" for Jmol 12.2)'
     },
     nucleic: {
-	'@desc': 'any group that (a) has one of the following group names: G, C, A, T, U, I, DG, DC, DA, DT, DU, DI, +G, +C, +A, +T, +U, +I; or (b) can be identified as a group that is only one atom, with name "P"; or (c) has all of the following atoms (prime, \', can replace * here): C1*, C2*, C3*, O3*, C4*, C5*, and O5*.',
-	map: () => nucleicExpr()
+        '@desc': 'any group that (a) has one of the following group names: G, C, A, T, U, I, DG, DC, DA, DT, DU, DI, +G, +C, +A, +T, +U, +I; or (b) can be identified as a group that is only one atom, with name "P"; or (c) has all of the following atoms (prime, \', can replace * here): C1*, C2*, C3*, O3*, C4*, C5*, and O5*.',
+        map: () => nucleicExpr()
     },
     purine: {
-	'@desc': 'any nucleic group that (a) has one of the following group names: A, G, I, DA, DG, DI, +A, +G, or +I; or (b) also has atoms N7, C8, and N9.',
-	map: () => B.struct.modifier.intersectBy({
+        '@desc': 'any nucleic group that (a) has one of the following group names: A, G, I, DA, DG, DI, +A, +G, or +I; or (b) also has atoms N7, C8, and N9.',
+        map: () => B.struct.modifier.intersectBy({
 	    0: nucleicExpr(),
 	    by: B.struct.combinator.merge([
-		B.struct.generator.atomGroups({
+                B.struct.generator.atomGroups({
 		    'residue-test': B.core.set.has([
-			B.set(...['A', 'G', 'I', 'DA', 'DG', 'DI', '+A', '+G', '+I']),
-			B.ammp('label_comp_id')
+                        B.set(...['A', 'G', 'I', 'DA', 'DG', 'DI', '+A', '+G', '+I']),
+                        B.ammp('label_comp_id')
 		    ])
-		}),
-		B.struct.filter.pick({
+                }),
+                B.struct.filter.pick({
 		    0: B.struct.generator.atomGroups({
-			'group-by': B.ammp('residueKey')
+                        'group-by': B.ammp('residueKey')
 		    }),
 		    test: B.core.set.isSubset([
-			h.atomNameSet([ 'N7', 'C8', 'N9' ]),
-			B.ammpSet('label_atom_id')
+                        h.atomNameSet(['N7', 'C8', 'N9']),
+                        B.ammpSet('label_atom_id')
 		    ])
-		})
+                })
 	    ])
-	})
+        })
     },
     pyrimidine: {
-	'@desc': 'any nucleic group that (a) has one of the following group names: C, T, U, DC, DT, DU, +C, +T, +U; or (b) also has atom O2.',
-	map: () => B.struct.modifier.intersectBy({
+        '@desc': 'any nucleic group that (a) has one of the following group names: C, T, U, DC, DT, DU, +C, +T, +U; or (b) also has atom O2.',
+        map: () => B.struct.modifier.intersectBy({
 	    0: nucleicExpr(),
 	    by: B.struct.combinator.merge([
-		B.struct.generator.atomGroups({
+                B.struct.generator.atomGroups({
 		    'residue-test': B.core.set.has([
-			B.set(...['C', 'T', 'U', 'DC', 'DT', 'DU', '+C', '+T', '+U']),
-			B.ammp('label_comp_id')
+                        B.set(...['C', 'T', 'U', 'DC', 'DT', 'DU', '+C', '+T', '+U']),
+                        B.ammp('label_comp_id')
 		    ])
-		}),
-		B.struct.filter.pick({
+                }),
+                B.struct.filter.pick({
 		    0: B.struct.generator.atomGroups({
-			'group-by': B.ammp('residueKey')
+                        'group-by': B.ammp('residueKey')
 		    }),
 		    test: B.core.logic.or([
-			B.core.set.has([
+                        B.core.set.has([
 			    B.ammpSet('label_atom_id'),
 			    B.atomName('O2*')
-			]),
-			B.core.set.has([
+                        ]),
+                        B.core.set.has([
 			    B.ammpSet('label_atom_id'),
 			    B.atomName("O2'")
-			])
+                        ])
 		    ])
-		})
+                })
 	    ])
-	})
+        })
     },
     dna: {
-	'@desc': 'any nucleic group that (a) has one of the following group names: DG, DC, DA, DT, DU, DI, T, +G, +C, +A, +T; or (b) has neither atom O2* or O2\'.',
-	map: () => B.struct.modifier.intersectBy({
+        '@desc': 'any nucleic group that (a) has one of the following group names: DG, DC, DA, DT, DU, DI, T, +G, +C, +A, +T; or (b) has neither atom O2* or O2\'.',
+        map: () => B.struct.modifier.intersectBy({
 	    0: nucleicExpr(),
 	    by: B.struct.combinator.merge([
-		B.struct.generator.atomGroups({
+                B.struct.generator.atomGroups({
 		    'residue-test': B.core.set.has([
-			B.set(...['DG', 'DC', 'DA', 'DT', 'DU', 'DI', 'T', '+G', '+C', '+A', '+T']),
-			B.ammp('label_comp_id')
+                        B.set(...['DG', 'DC', 'DA', 'DT', 'DU', 'DI', 'T', '+G', '+C', '+A', '+T']),
+                        B.ammp('label_comp_id')
 		    ])
-		}),
-		B.struct.filter.pick({
+                }),
+                B.struct.filter.pick({
 		    0: B.struct.generator.atomGroups({
-			'group-by': B.ammp('residueKey')
+                        'group-by': B.ammp('residueKey')
 		    }),
 		    test: B.core.logic.not([
-			B.core.logic.or([
+                        B.core.logic.or([
 			    B.core.set.has([
-				B.ammpSet('label_atom_id'),
-				B.atomName('O2*')
+                                B.ammpSet('label_atom_id'),
+                                B.atomName('O2*')
 			    ]),
 			    B.core.set.has([
-				B.ammpSet('label_atom_id'),
-				B.atomName("O2'")
+                                B.ammpSet('label_atom_id'),
+                                B.atomName("O2'")
 			    ])
-			])
+                        ])
 		    ])
-		})
+                })
 	    ])
-	})
+        })
     },
     rna: {
-	'@desc': 'any nucleic group that (a) has one of the following group names: G, C, A, U, I, +U, +I; or (b) has atom O2* or O2\'.',
-	map: () => B.struct.modifier.intersectBy({
+        '@desc': 'any nucleic group that (a) has one of the following group names: G, C, A, U, I, +U, +I; or (b) has atom O2* or O2\'.',
+        map: () => B.struct.modifier.intersectBy({
 	    0: nucleicExpr(),
 	    by: B.struct.combinator.merge([
-		B.struct.generator.atomGroups({
+                B.struct.generator.atomGroups({
 		    'residue-test': B.core.set.has([
-			B.set(...['G', 'C', 'A', 'U', 'I', '+U', '+I']),
-			B.ammp('label_comp_id')
+                        B.set(...['G', 'C', 'A', 'U', 'I', '+U', '+I']),
+                        B.ammp('label_comp_id')
 		    ])
-		}),
-		B.struct.filter.pick({
+                }),
+                B.struct.filter.pick({
 		    0: B.struct.generator.atomGroups({
-			'group-by': B.ammp('residueKey')
+                        'group-by': B.ammp('residueKey')
 		    }),
 		    test: B.core.logic.or([
-			B.core.set.has([
+                        B.core.set.has([
 			    B.ammpSet('label_atom_id'),
 			    B.atomName('O2*')
-			]),
-			B.core.set.has([
+                        ]),
+                        B.core.set.has([
 			    B.ammpSet('label_atom_id'),
 			    B.atomName("O2'")
-			])
+                        ])
 		    ])
-		})
+                })
 	    ])
-	})
+        })
     },
     protein: {
-	'@desc': 'defined as a group that (a) has one of the following group names: ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU}, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, ASX, GLX, or UNK; or (b) contains PDB atom designations [C, O, CA, and N] bonded correctly; or (c) does not contain "O" but contains [C, CA, and N] bonded correctly; or (d) has only one atom, which has name CA and does not have the group name CA (indicating a calcium atom).',
-	map: () => proteinExpr()	
+        '@desc': 'defined as a group that (a) has one of the following group names: ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU}, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, ASX, GLX, or UNK; or (b) contains PDB atom designations [C, O, CA, and N] bonded correctly; or (c) does not contain "O" but contains [C, CA, and N] bonded correctly; or (d) has only one atom, which has name CA and does not have the group name CA (indicating a calcium atom).',
+        map: () => proteinExpr()
     },
     acidic: {
-	'@desc': 'ASP GLU',
-      map: () => h.resnameExpr(ResDict.acidic)
-  },
+        '@desc': 'ASP GLU',
+        map: () => h.resnameExpr(ResDict.acidic)
+    },
     acyclic: {
-      '@desc': 'amino and not cyclic',
-      map: () => B.struct.modifier.intersectBy({
-	0: h.resnameExpr(ResDict.amino),
-	by: h.invertExpr(h.resnameExpr(ResDict.cyclic))
-    })
-  },
+        '@desc': 'amino and not cyclic',
+        map: () => B.struct.modifier.intersectBy({
+            0: h.resnameExpr(ResDict.amino),
+            by: h.invertExpr(h.resnameExpr(ResDict.cyclic))
+        })
+    },
     aliphatic: {
-      '@desc': 'ALA GLY ILE LEU VAL',
-      map: () => h.resnameExpr(ResDict.aliphatic)
-  },
+        '@desc': 'ALA GLY ILE LEU VAL',
+        map: () => h.resnameExpr(ResDict.aliphatic)
+    },
     amino: {
-      '@desc': 'all twenty standard amino acids, plus ASX, GLX, UNK',
-      map: () => h.resnameExpr(ResDict.amino)
-  },
+        '@desc': 'all twenty standard amino acids, plus ASX, GLX, UNK',
+        map: () => h.resnameExpr(ResDict.amino)
+    },
     aromatic: {
-      '@desc': 'HIS PHE TRP TYR (see also "isaromatic" for aromatic bonds)',
-      map: () => h.resnameExpr(ResDict.aromatic)
-  },
+        '@desc': 'HIS PHE TRP TYR (see also "isaromatic" for aromatic bonds)',
+        map: () => h.resnameExpr(ResDict.aromatic)
+    },
     basic: {
-      '@desc': 'ARG HIS LYS',
-      map: () => h.resnameExpr(ResDict.basic)
-  },
+        '@desc': 'ARG HIS LYS',
+        map: () => h.resnameExpr(ResDict.basic)
+    },
     buried: {
-      '@desc': 'ALA CYS ILE LEU MET PHE TRP VAL',
-      map: () => h.resnameExpr(ResDict.buried)
-  },
+        '@desc': 'ALA CYS ILE LEU MET PHE TRP VAL',
+        map: () => h.resnameExpr(ResDict.buried)
+    },
     charged: {
-      '@desc': 'same as acidic or basic -- ASP GLU, ARG HIS LYS',
-      map: () => h.resnameExpr(ResDict.acidic.concat(ResDict.basic))
-  },
+        '@desc': 'same as acidic or basic -- ASP GLU, ARG HIS LYS',
+        map: () => h.resnameExpr(ResDict.acidic.concat(ResDict.basic))
+    },
     cyclic: {
-      '@desc': 'HIS PHE PRO TRP TYR',
-      map: () => h.resnameExpr(ResDict.cyclic)
-  },
+        '@desc': 'HIS PHE PRO TRP TYR',
+        map: () => h.resnameExpr(ResDict.cyclic)
+    },
     helix: {
-      '@desc': 'secondary structure-related.',
-      map: () => B.struct.generator.atomGroups({
-	'residue-test': B.core.flags.hasAny([
-          B.struct.type.secondaryStructureFlags(['helix']),
-          B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
+        '@desc': 'secondary structure-related.',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['helix']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
     hetero: {
-      '@desc': 'PDB atoms designated as HETATM',
-      map: () => B.struct.generator.atomGroups({
-	'atom-test': B.ammp('isHet')
-    })
-  },
+        '@desc': 'PDB atoms designated as HETATM',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.ammp('isHet')
+        })
+    },
     hydrophobic: {
-      '@desc': 'ALA GLY ILE LEU MET PHE PRO TRP TYR VAL',
-      map: () => h.resnameExpr(ResDict.hydrophobic)
-  },
+        '@desc': 'ALA GLY ILE LEU MET PHE PRO TRP TYR VAL',
+        map: () => h.resnameExpr(ResDict.hydrophobic)
+    },
     large: {
-      '@desc': 'ARG GLU GLN HIS ILE LEU LYS MET PHE TRP TYR',
-      map: () => h.resnameExpr(ResDict.large)
-  },
+        '@desc': 'ARG GLU GLN HIS ILE LEU LYS MET PHE TRP TYR',
+        map: () => h.resnameExpr(ResDict.large)
+    },
     medium: {
-      '@desc': 'ASN ASP CYS PRO THR VAL',
-      map: () => h.resnameExpr(ResDict.medium)
-  },
+        '@desc': 'ASN ASP CYS PRO THR VAL',
+        map: () => h.resnameExpr(ResDict.medium)
+    },
     negative: {
-      '@desc': 'same as acidic -- ASP GLU',
-      map: () => h.resnameExpr(ResDict.acidic)
-  },
+        '@desc': 'same as acidic -- ASP GLU',
+        map: () => h.resnameExpr(ResDict.acidic)
+    },
     neutral: {
-      '@desc': 'amino and not (acidic or basic)',
-      map: () => B.struct.modifier.intersectBy({
-	0: h.resnameExpr(ResDict.amino),
-	by: h.invertExpr(h.resnameExpr(ResDict.acidic.concat(ResDict.basic)))
-    })
-  },
+        '@desc': 'amino and not (acidic or basic)',
+        map: () => B.struct.modifier.intersectBy({
+            0: h.resnameExpr(ResDict.amino),
+            by: h.invertExpr(h.resnameExpr(ResDict.acidic.concat(ResDict.basic)))
+        })
+    },
     polar: {
-      '@desc': 'amino and not hydrophobic',
-      map: () => B.struct.modifier.intersectBy({
-	0: h.resnameExpr(ResDict.amino),
-	by: h.invertExpr(h.resnameExpr(ResDict.hydrophobic))
-    })
-  },
+        '@desc': 'amino and not hydrophobic',
+        map: () => B.struct.modifier.intersectBy({
+            0: h.resnameExpr(ResDict.amino),
+            by: h.invertExpr(h.resnameExpr(ResDict.hydrophobic))
+        })
+    },
     positive: {
-      '@desc': 'same as basic -- ARG HIS LYS',
-      map: () => h.resnameExpr(ResDict.basic)
-  },
+        '@desc': 'same as basic -- ARG HIS LYS',
+        map: () => h.resnameExpr(ResDict.basic)
+    },
     sheet: {
-      '@desc': 'secondary structure-related',
-      map: () => B.struct.generator.atomGroups({
-	'residue-test': B.core.flags.hasAny([
-          B.struct.type.secondaryStructureFlags(['sheet']),
-          B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
+        '@desc': 'secondary structure-related',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['sheet']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
     small: {
-      '@desc': 'ALA GLY SER',
-      map: () => h.resnameExpr(ResDict.small)
-  },
+        '@desc': 'ALA GLY SER',
+        map: () => h.resnameExpr(ResDict.small)
+    },
     turn: {
-      '@desc': 'secondary structure-related',
-      map: () => B.struct.generator.atomGroups({
-	'residue-test': B.core.flags.hasAny([
-          B.struct.type.secondaryStructureFlags(['turn']),
-          B.ammp('secondaryStructureFlags')
-      ])
-    })
-  },
+        '@desc': 'secondary structure-related',
+        map: () => B.struct.generator.atomGroups({
+            'residue-test': B.core.flags.hasAny([
+                B.struct.type.secondaryStructureFlags(['turn']),
+                B.ammp('secondaryStructureFlags')
+            ])
+        })
+    },
     alpha: {
-      '@desc': '(*.CA)',
-      map: () => B.struct.generator.atomGroups({
-	'atom-test': B.core.rel.eq([
-          B.atomName('CA'),
-          B.ammp('label_atom_id')
-      ])
-    })
-  },
+        '@desc': '(*.CA)',
+        map: () => B.struct.generator.atomGroups({
+            'atom-test': B.core.rel.eq([
+                B.atomName('CA'),
+                B.ammp('label_atom_id')
+            ])
+        })
+    },
     base: {
-      '@desc': '(nucleic bases)'
-  },
+        '@desc': '(nucleic bases)'
+    },
     backbone: {
-      '@desc': '(*.C, *.CA, *.N, and all nucleic other than the bases themselves)',
-      abbr: ['mainchain'],
-      map: () => backboneExpr()
-  },
+        '@desc': '(*.C, *.CA, *.N, and all nucleic other than the bases themselves)',
+        abbr: ['mainchain'],
+        map: () => backboneExpr()
+    },
     sidechain: {
-	'@desc': '((protein or nucleic) and not backbone)'
-  },
+        '@desc': '((protein or nucleic) and not backbone)'
+    },
     solvent: {
-	'@desc': 'PDB "HOH", water, also the connected set of H-O-H in any model',
-	    map: () => h.resnameExpr(ResDict.solvent)	
+        '@desc': 'PDB "HOH", water, also the connected set of H-O-H in any model',
+	    map: () => h.resnameExpr(ResDict.solvent)
     },
 };
 

+ 30 - 30
src/mol-script/transpilers/rasmol/markdown-docs.ts

@@ -1,9 +1,9 @@
-/* 
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
- * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                     
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com> 
- * 
- * @author Koya Sakuma 
+/*
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
+ *
+ * @author Koya Sakuma
  * This module is based on jmol transpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             */
 
 import { properties } from './properties';
@@ -11,53 +11,53 @@ import { operators } from './operators';
 import { keywords } from './keywords';
 
 
-const docs: string[] = [
+const _docs: string[] = [
     'Jmol',
     '============',
     '--------------------------------',
     ''
 ];
 
-docs.push(`## Properties\n\n`);
-docs.push('--------------------------------\n');
+_docs.push(`## Properties\n\n`);
+_docs.push('--------------------------------\n');
 for (const name in properties) {
-    if (properties[name].isUnsupported) continue
+    if (properties[name].isUnsupported) continue;
 
-    const names = [name]
-    if (properties[name].abbr) names.push(...properties[name].abbr!)
-    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+    const names = [name];
+    if (properties[name].abbr) names.push(...properties[name].abbr!);
+    _docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
 
     if (properties[name]['@desc']) {
-        docs.push(`*${properties[name]['@desc']}*\n`);
+        _docs.push(`*${properties[name]['@desc']}*\n`);
     }
 }
 
-docs.push(`## Operators\n\n`);
-docs.push('--------------------------------\n');
+_docs.push(`## Operators\n\n`);
+_docs.push('--------------------------------\n');
 operators.forEach(o => {
-    if (o.isUnsupported) return
+    if (o.isUnsupported) return;
 
-    const names = [o.name]
-    if (o.abbr) names.push(...o.abbr!)
-    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+    const names = [o.name];
+    if (o.abbr) names.push(...o.abbr!);
+    _docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
 
     if (o['@desc']) {
-        docs.push(`*${o['@desc']}*\n`);
+        _docs.push(`*${o['@desc']}*\n`);
     }
-})
+});
 
-docs.push(`## Keywords\n\n`);
-docs.push('--------------------------------\n');
+_docs.push(`## Keywords\n\n`);
+_docs.push('--------------------------------\n');
 for (const name in keywords) {
-    if (!keywords[name].map) continue
+    if (!keywords[name].map) continue;
 
-    const names = [name]
-    if (keywords[name].abbr) names.push(...keywords[name].abbr!)
-    docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
+    const names = [name];
+    if (keywords[name].abbr) names.push(...keywords[name].abbr!);
+    _docs.push(`\`\`\`\n${names.join(', ')}\n\`\`\`\n`);
 
     if (keywords[name]['@desc']) {
-        docs.push(`*${keywords[name]['@desc']}*\n`);
+        _docs.push(`*${keywords[name]['@desc']}*\n`);
     }
 }
 
-export default docs.join('\n')
+export const docs = _docs.join('\n');

+ 32 - 32
src/mol-script/transpilers/rasmol/operators.ts

@@ -1,9 +1,9 @@
-/*       
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.    
- * @author Alexander Rose <alexander.rose@weirdbyte.de>               
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>           
- *                                                                    
- * @author Koya Sakuma                                                
+/*
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
+ *
+ * @author Koya Sakuma
  * This module is based on jmol transpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             \
  */
 
@@ -13,33 +13,33 @@ import * as h from '../helper';
 import { MolScriptBuilder } from '../../../mol-script/language/builder';
 const B = MolScriptBuilder;
 import { OperatorList } from '../types';
-//import { Expression } from '../../language/expression';
+// import { Expression } from '../../language/expression';
 
 
 export const operators: OperatorList = [
-  {
-    '@desc': 'Selects atoms that are not included in s1.',
-    '@examples': ['not ARG'],
-    name: 'not',
-    type: h.prefix,
-    rule: P.MonadicParser.alt(P.MonadicParser.regex(/NOT/i).skip(P.MonadicParser.whitespace), P.MonadicParser.string('!').skip(P.MonadicParser.optWhitespace)),
-    map: (op, selection) => h.invertExpr(selection),
-  },
-  {
-    '@desc': 'Selects atoms included in both s1 and s2.',
-    '@examples': ['ASP and .CA'],
-    name: 'and',
-    type: h.binaryLeft,
-    rule: h.infixOp(/AND|&/i),
-    map: (op, selection, by) => B.struct.modifier.intersectBy({ 0: selection, by })
-  },
-  {
-    '@desc': 'Selects atoms included in either s1 or s2.',
-    '@examples': ['ASP or GLU'],
-    name: 'or',
-    type: h.binaryLeft,
-    rule: h.infixOp(/OR|\|/i),
-    map: (op, s1, s2) => B.struct.combinator.merge([s1, s2])
-  }
-]
+    {
+        '@desc': 'Selects atoms that are not included in s1.',
+        '@examples': ['not ARG'],
+        name: 'not',
+        type: h.prefix,
+        rule: P.MonadicParser.alt(P.MonadicParser.regex(/NOT/i).skip(P.MonadicParser.whitespace), P.MonadicParser.string('!').skip(P.MonadicParser.optWhitespace)),
+        map: (op, selection) => h.invertExpr(selection),
+    },
+    {
+        '@desc': 'Selects atoms included in both s1 and s2.',
+        '@examples': ['ASP and .CA'],
+        name: 'and',
+        type: h.binaryLeft,
+        rule: h.infixOp(/AND|&/i),
+        map: (op, selection, by) => B.struct.modifier.intersectBy({ 0: selection, by })
+    },
+    {
+        '@desc': 'Selects atoms included in either s1 or s2.',
+        '@examples': ['ASP or GLU'],
+        name: 'or',
+        type: h.binaryLeft,
+        rule: h.infixOp(/OR|\|/i),
+        map: (op, s1, s2) => B.struct.combinator.merge([s1, s2])
+    }
+];
 

+ 196 - 197
src/mol-script/transpilers/rasmol/parser.ts

@@ -1,7 +1,7 @@
 /**
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                     
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
  * @author Koya Sakuma
  * This module is based on jmol tranpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.
  **/
@@ -18,147 +18,147 @@ import { AtomGroupArgs } from '../types';
 import { Transpiler } from '../transpiler';
 import { OperatorList } from '../types';
 
-//const propertiesDict = h.getPropertyRules(properties);
+// const propertiesDict = h.getPropertyRules(properties);
 
-//const slash = P.MonadicParser.string('/');
+// const slash = P.MonadicParser.string('/');
 
 
 // <, <=, =, >=, >, !=, and LIKE
 const valueOperators: OperatorList = [
-  {
-    '@desc': 'value comparisons',
-    '@examples': [],
-    name: '=',
-    abbr: ['=='],
-    type: h.binaryLeft,
-    rule: P.MonadicParser.regexp(/\s*(LIKE|>=|<=|=|!=|>|<)\s*/i, 1),
-    map: (op, e1, e2) => {
-      // console.log(op, e1, e2)
-      let expr
-      if (e1 === 'structure') {
-        expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e2)])
-      } else if (e2 === 'structure') {
-        expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e1)])
-      } else if (e1.head === 'core.type.regex') {
-        expr = B.core.str.match([ e1, B.core.type.str([e2]) ])
-      } else if (e2.head === 'core.type.regex') {
-        expr = B.core.str.match([ e2, B.core.type.str([e1]) ])
-      } else if (op.toUpperCase() === 'LIKE') {
-        if (e1.head) {
-          expr = B.core.str.match([
-            B.core.type.regex([`^${e2}$`, 'i']),
-            B.core.type.str([e1])
-          ])
-        } else {
-          expr = B.core.str.match([
-            B.core.type.regex([`^${e1}$`, 'i']),
-            B.core.type.str([e2])
-          ])
+    {
+        '@desc': 'value comparisons',
+        '@examples': [],
+        name: '=',
+        abbr: ['=='],
+        type: h.binaryLeft,
+        rule: P.MonadicParser.regexp(/\s*(LIKE|>=|<=|=|!=|>|<)\s*/i, 1),
+        map: (op, e1, e2) => {
+            // console.log(op, e1, e2)
+            let expr;
+            if (e1 === 'structure') {
+                expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e2)]);
+            } else if (e2 === 'structure') {
+                expr = B.core.flags.hasAny([B.ammp('secondaryStructureFlags'), structureMap(e1)]);
+            } else if (e1.head === 'core.type.regex') {
+                expr = B.core.str.match([e1, B.core.type.str([e2])]);
+            } else if (e2.head === 'core.type.regex') {
+                expr = B.core.str.match([e2, B.core.type.str([e1])]);
+            } else if (op.toUpperCase() === 'LIKE') {
+                if (e1.head) {
+                    expr = B.core.str.match([
+                        B.core.type.regex([`^${e2}$`, 'i']),
+                        B.core.type.str([e1])
+                    ]);
+                } else {
+                    expr = B.core.str.match([
+                        B.core.type.regex([`^${e1}$`, 'i']),
+                        B.core.type.str([e2])
+                    ]);
+                }
+            }
+            if (!expr) {
+                if (e1.head) e2 = h.wrapValue(e1, e2);
+                if (e2.head) e1 = h.wrapValue(e2, e1);
+                switch (op) {
+                    case '=':
+                        expr = B.core.rel.eq([e1, e2]);
+                        break;
+                    case '!=':
+                        expr = B.core.rel.neq([e1, e2]);
+                        break;
+                    case '>':
+                        expr = B.core.rel.gr([e1, e2]);
+                        break;
+                    case '<':
+                        expr = B.core.rel.lt([e1, e2]);
+                        break;
+                    case '>=':
+                        expr = B.core.rel.gre([e1, e2]);
+                        break;
+                    case '<=':
+                        expr = B.core.rel.lte([e1, e2]);
+                        break;
+                    default: throw new Error(`value operator '${op}' not supported`);
+                }
+            }
+            return B.struct.generator.atomGroups({ 'atom-test': expr });
         }
-      }
-      if (!expr) {
-        if (e1.head) e2 = h.wrapValue(e1, e2)
-        if (e2.head) e1 = h.wrapValue(e2, e1)
-        switch (op) {
-          case '=':
-            expr = B.core.rel.eq([e1, e2])
-            break
-          case '!=':
-            expr = B.core.rel.neq([e1, e2])
-            break
-          case '>':
-            expr = B.core.rel.gr([e1, e2])
-            break
-          case '<':
-            expr = B.core.rel.lt([e1, e2])
-            break
-          case '>=':
-            expr = B.core.rel.gre([e1, e2])
-            break
-          case '<=':
-            expr = B.core.rel.lte([e1, e2])
-            break
-          default: throw new Error(`value operator '${op}' not supported`);
-        }
-      }
-      return B.struct.generator.atomGroups({ 'atom-test': expr })
     }
-  }
-]
+];
 
-function atomExpressionQuery (x: any[]) {
-  const [resno, inscode, chainname, atomname, altloc, ] = x[1]
-  const tests: AtomGroupArgs = {}
+function atomExpressionQuery(x: any[]) {
+    const [resno, inscode, chainname, atomname, altloc] = x[1];
+    const tests: AtomGroupArgs = {};
 
-  if (chainname) {
+    if (chainname) {
     // should be configurable, there is an option in Jmol to use auth or label
-    tests['chain-test'] = B.core.rel.eq([ B.ammp('auth_asym_id'), chainname ])
-  }
+        tests['chain-test'] = B.core.rel.eq([B.ammp('auth_asym_id'), chainname]);
+    }
 
-  const resProps = []
-  if (resno) resProps.push(B.core.rel.eq([ B.ammp('auth_seq_id'), resno ]))
-  if (inscode) resProps.push(B.core.rel.eq([ B.ammp('pdbx_PDB_ins_code'), inscode ]))
-  if (resProps.length) tests['residue-test'] = h.andExpr(resProps)
+    const resProps = [];
+    if (resno) resProps.push(B.core.rel.eq([B.ammp('auth_seq_id'), resno]));
+    if (inscode) resProps.push(B.core.rel.eq([B.ammp('pdbx_PDB_ins_code'), inscode]));
+    if (resProps.length) tests['residue-test'] = h.andExpr(resProps);
 
-  const atomProps = []
-  if (atomname) atomProps.push(B.core.rel.eq([ B.ammp('auth_atom_id'), atomname ]))
-  if (altloc) atomProps.push(B.core.rel.eq([ B.ammp('label_alt_id'), altloc ]))
-  if (atomProps.length) tests['atom-test'] = h.andExpr(atomProps)
+    const atomProps = [];
+    if (atomname) atomProps.push(B.core.rel.eq([B.ammp('auth_atom_id'), atomname]));
+    if (altloc) atomProps.push(B.core.rel.eq([B.ammp('label_alt_id'), altloc]));
+    if (atomProps.length) tests['atom-test'] = h.andExpr(atomProps);
 
-  return B.struct.generator.atomGroups(tests)
+    return B.struct.generator.atomGroups(tests);
 }
 
 const lang = P.MonadicParser.createLanguage({
-  Integer: () => P.MonadicParser.regexp(/-?[0-9]+/).map(Number).desc('integer'),
-
-    Parens: function (r:any) {
-    return P.MonadicParser.alt(
-      r.Parens,
-      r.Operator,
-      r.Expression
-    ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'))
-  },
-
-    Expression: function(r:any) {
-	return P.MonadicParser.alt(
+    Integer: () => P.MonadicParser.regexp(/-?[0-9]+/).map(Number).desc('integer'),
+
+    Parens: function (r: any) {
+        return P.MonadicParser.alt(
+            r.Parens,
+            r.Operator,
+            r.Expression
+        ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
+    },
+
+    Expression: function (r: any) {
+        return P.MonadicParser.alt(
 	    r.NamedAtomProperties,
 	    r.Keywords,
-	    r.Resno.lookahead(P.MonadicParser.regexp(/\s*(?!(LIKE|>=|<=|!=|[:^%/.=><]))/i)).map((x:any) => B.struct.generator.atomGroups({
-		'residue-test': B.core.rel.eq([ B.ammp('auth_seq_id'), x ])
+	    r.Resno.lookahead(P.MonadicParser.regexp(/\s*(?!(LIKE|>=|<=|!=|[:^%/.=><]))/i)).map((x: any) => B.struct.generator.atomGroups({
+                'residue-test': B.core.rel.eq([B.ammp('auth_seq_id'), x])
 	    })),
 	    r.AtomExpression.map(atomExpressionQuery),
-	    
+
 	    r.ValueQuery,
-	    
+
 	    r.Element.map((x: string) => B.struct.generator.atomGroups({
-		'atom-test': B.core.rel.eq([ B.acp('elementSymbol'), B.struct.type.elementSymbol(x) ])
+                'atom-test': B.core.rel.eq([B.acp('elementSymbol'), B.struct.type.elementSymbol(x)])
 	    })),
 	    r.Resname.map((x: string) => B.struct.generator.atomGroups({
-		'residue-test': B.core.rel.eq([ B.ammp('label_comp_id'), x ])
+                'residue-test': B.core.rel.eq([B.ammp('label_comp_id'), x])
 	    })),
-	)
+        );
     },
 
     NamedAtomProperties: function () {
-        return P.MonadicParser.alt(...h.getNamedPropertyRules(properties)); 
+        return P.MonadicParser.alt(...h.getNamedPropertyRules(properties));
     },
 
-Operator: function(r:any) {
-    return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression))
-  },
-
-AtomExpression: function(r:any) {
-    return P.MonadicParser.seq(
-	P.MonadicParser.lookahead(r.AtomPrefix),
-	P.MonadicParser.seq(
-            r.Resno.or(P.MonadicParser.of(null)),
-            r.Inscode.or(P.MonadicParser.of(null)),
-            r.Chainname.or(P.MonadicParser.of(null)),
-            r.Atomname.or(P.MonadicParser.of(null)),
-            r.Altloc.or(P.MonadicParser.of(null)),
-            r.Model.or(P.MonadicParser.of(null))),	
-    )
-  },
+    Operator: function (r: any) {
+        return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression));
+    },
+
+    AtomExpression: function (r: any) {
+        return P.MonadicParser.seq(
+            P.MonadicParser.lookahead(r.AtomPrefix),
+            P.MonadicParser.seq(
+                r.Resno.or(P.MonadicParser.of(null)),
+                r.Inscode.or(P.MonadicParser.of(null)),
+                r.Chainname.or(P.MonadicParser.of(null)),
+                r.Atomname.or(P.MonadicParser.of(null)),
+                r.Altloc.or(P.MonadicParser.of(null)),
+                r.Model.or(P.MonadicParser.of(null))),
+        );
+    },
 
     AtomPrefix: () => P.MonadicParser.regexp(/[0-9:^%/.]/).desc('atom-prefix'),
     Chainname: () => P.MonadicParser.regexp(/:([A-Za-z]{1,3})/, 1).desc('chainname'),
@@ -166,99 +166,98 @@ AtomExpression: function(r:any) {
     Element: () => P.MonadicParser.regexp(/_([A-Za-z]{1,3})/, 1).desc('element'),
     Atomname: () => P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1).map(B.atomName).desc('atomname'),
     Resname: () => P.MonadicParser.regexp(/[a-zA-Z0-9]{1,4}/).desc('resname'),
-    Resno: (r:any) => r.Integer.desc('resno'),
-    Resno2: (r:any) => r.split(',').Integer.desc("resno"),
+    Resno: (r: any) => r.Integer.desc('resno'),
+    Resno2: (r: any) => r.split(',').Integer.desc('resno'),
     Altloc: () => P.MonadicParser.regexp(/%([a-zA-Z0-9])/, 1).desc('altloc'),
     Inscode: () => P.MonadicParser.regexp(/\^([a-zA-Z0-9])/, 1).desc('inscode'),
 
 
-//    function listMap(x: string) { return x.split(',').map(x => x.replace(/^["']|["']$/g, '')); }
+    //    function listMap(x: string) { return x.split(',').map(x => x.replace(/^["']|["']$/g, '')); }
+
 
 
+    BracketedResname: function (r: any) {
+        return P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1)
+	    .desc('bracketed-resname');
+        // [0SD]
+    },
 
-    BracketedResname: function (r:any) {
-	return P.MonadicParser.regexp(/\.([a-zA-Z0-9]{1,4})/, 1)
-	    .desc('bracketed-resname')
-	// [0SD]
+    ResnoRange: function (r: any) {
+        return P.MonadicParser.regexp(/\.([\s]){1,3}/, 1)
+	    .desc('resno-range');
+        // 123-200
+        // -12--3
     },
 
-    ResnoRange: function (r:any) {
-	return P.MonadicParser.regexp(/\.([\s]){1,3}/, 1)
-	    .desc('resno-range')
-	// 123-200
-	// -12--3
+    Keywords: () => P.MonadicParser.alt(...h.getKeywordRules(keywords)),
+
+    Query: function (r: any) {
+        return P.MonadicParser.alt(
+            r.Operator,
+            r.Parens,
+            r.Expression
+        ).trim(P.MonadicParser.optWhitespace);
     },
 
-  Keywords: () => P.MonadicParser.alt(...h.getKeywordRules(keywords)),
-
-Query: function(r:any) {
-    return P.MonadicParser.alt(
-      r.Operator,
-      r.Parens,
-      r.Expression
-    ).trim(P.MonadicParser.optWhitespace)
-  },
-
-  Number: function () {
-    return P.MonadicParser.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/)
-      .map(Number)
-      .desc('number')
-  },
-
-  String: function () {
-    const w = h.getReservedWords(properties, keywords, operators)
-      .sort(h.strLenSortFn).map(h.escapeRegExp).join('|')
-    return P.MonadicParser.alt(
-      P.MonadicParser.regexp(new RegExp(`(?!(${w}))[A-Z0-9_]+`, 'i')),
-      P.MonadicParser.regexp(/'((?:[^"\\]|\\.)*)'/, 1),
-      P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map(x => B.core.type.regex([`^${x}$`, 'i']))
-    )
-  },
-
-Value: function (r:any) {
-    return P.MonadicParser.alt(r.Number, r.String)
-  },
-
-ValueParens: function (r:any) {
-    return P.MonadicParser.alt(
-      r.ValueParens,
-      r.ValueOperator,
-      r.ValueExpressions
-    ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'))
-  },
-
-  ValuePropertyNames: function() {
-    return P.MonadicParser.alt(...h.getPropertyNameRules(properties, /LIKE|>=|<=|=|!=|>|<|\)|\s/i))
-  },
-
-ValueOperator: function(r:any) {
-    return h.combineOperators(valueOperators, P.MonadicParser.alt(r.ValueParens, r.ValueExpressions))
-  },
-
-ValueExpressions: function(r:any) {
-    return P.MonadicParser.alt(
-      r.Value,
-      r.ValuePropertyNames
-    )
-  },
-
-ValueQuery: function(r:any) {
-    return P.MonadicParser.alt(
-	r.ValueOperator.map((x:any) => {
-        if (x.head) {
-          if (x.head.startsWith('structure-query.generator')) return x
-        } else {
-          if (typeof x === 'string' && x.length <= 4) {
-            return B.struct.generator.atomGroups({
-              'residue-test': B.core.rel.eq([ B.ammp('label_comp_id'), x ])
+    Number: function () {
+        return P.MonadicParser.regexp(/-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?/)
+            .map(Number)
+            .desc('number');
+    },
+
+    String: function () {
+        const w = h.getReservedWords(properties, keywords, operators)
+            .sort(h.strLenSortFn).map(h.escapeRegExp).join('|');
+        return P.MonadicParser.alt(
+            P.MonadicParser.regexp(new RegExp(`(?!(${w}))[A-Z0-9_]+`, 'i')),
+            P.MonadicParser.regexp(/'((?:[^"\\]|\\.)*)'/, 1),
+            P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map(x => B.core.type.regex([`^${x}$`, 'i']))
+        );
+    },
+
+    Value: function (r: any) {
+        return P.MonadicParser.alt(r.Number, r.String);
+    },
+
+    ValueParens: function (r: any) {
+        return P.MonadicParser.alt(
+            r.ValueParens,
+            r.ValueOperator,
+            r.ValueExpressions
+        ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
+    },
+
+    ValuePropertyNames: function () {
+        return P.MonadicParser.alt(...h.getPropertyNameRules(properties, /LIKE|>=|<=|=|!=|>|<|\)|\s/i));
+    },
+
+    ValueOperator: function (r: any) {
+        return h.combineOperators(valueOperators, P.MonadicParser.alt(r.ValueParens, r.ValueExpressions));
+    },
+
+    ValueExpressions: function (r: any) {
+        return P.MonadicParser.alt(
+            r.Value,
+            r.ValuePropertyNames
+        );
+    },
+
+    ValueQuery: function (r: any) {
+        return P.MonadicParser.alt(
+            r.ValueOperator.map((x: any) => {
+                if (x.head) {
+                    if (x.head.startsWith('structure-query.generator')) return x;
+                } else {
+                    if (typeof x === 'string' && x.length <= 4) {
+                        return B.struct.generator.atomGroups({
+                            'residue-test': B.core.rel.eq([B.ammp('label_comp_id'), x])
+                        });
+                    }
+                }
+                throw new Error(`values must be part of an comparison, value '${x}'`);
             })
-          }
-        }
-        throw new Error(`values must be part of an comparison, value '${x}'`)
-      })
-    )
-  }
-})
-
-const transpiler: Transpiler = str => lang.Query.tryParse(str)
-export default transpiler
+        );
+    }
+});
+
+export const transpiler: Transpiler = str => lang.Query.tryParse(str);

File diff suppressed because it is too large
+ 43 - 512
src/mol-script/transpilers/rasmol/properties.ts


+ 20 - 21
src/mol-script/transpilers/rasmol/symbols.ts

@@ -1,9 +1,9 @@
-/*                                                                                                                                           
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.                                           
- * @author Alexander Rose <alexander.rose@weirdbyte.de>                                                                                     
- * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>                                                                                 
- *                                                                                                                                           
- * @author Koya Sakuma                                                                                                                       
+/*
+ * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ * @author Panagiotis Tourlas <panagiot_tourlov@hotmail.com>
+ *
+ * @author Koya Sakuma
  * This module is based on jmol tranpiler from MolQL and modified in similar manner as pymol and vmd tranpilers.                                             \
 */
 
@@ -11,26 +11,25 @@ import { properties } from './properties';
 import { operators } from './operators';
 import { keywords } from './keywords';
 
-export const Properties: string[] = []
+export const Properties: string[] = [];
 for (const name in properties) {
-    if (properties[name].isUnsupported) continue
-    Properties.push(name)
-    if (properties[name].abbr) Properties.push(...properties[name].abbr!)
+    if (properties[name].isUnsupported) continue;
+    Properties.push(name);
+    if (properties[name].abbr) Properties.push(...properties[name].abbr!);
 }
 
-export const Operators: string[] = []
+export const Operators: string[] = [];
 operators.forEach(o => {
-    if (o.isUnsupported) return
-    Operators.push(o.name)
-    if (o.abbr) Operators.push(...o.abbr)
-})
+    if (o.isUnsupported) return;
+    Operators.push(o.name);
+    if (o.abbr) Operators.push(...o.abbr);
+});
 
-export const Keywords: string[] = []
+export const Keywords: string[] = [];
 for (const name in keywords) {
-    if (!keywords[name].map) continue
-    Keywords.push(name)
-    if (keywords[name].abbr) Keywords.push(...keywords[name].abbr!)
+    if (!keywords[name].map) continue;
+    Keywords.push(name);
+    if (keywords[name].abbr) Keywords.push(...keywords[name].abbr!);
 }
 
-const _all = { Properties, Operators, Keywords }
-export default _all
+export const _all = { Properties, Operators, Keywords };

+ 1 - 1
src/mol-script/transpilers/transpiler.ts

@@ -9,4 +9,4 @@ import { Expression } from '../language/expression';
 
 export type Transpiler = (source: string) => Expression
 
-export default Transpiler
+export const Transpiler = (source: string) => Expression;

+ 3 - 3
src/mol-script/transpilers/vmd/operators.ts

@@ -30,7 +30,7 @@ export const operators: OperatorList = [
         '@examples': ['within 5 of name FE'],
         name: 'within',
         type: h.prefix,
-        rule: h.prefixOp(/WITHIN\s+([-+]?[0-9]*\.?[0-9]+)\s+OF/i, 1).map((x:any) => parseFloat(x)),
+        rule: h.prefixOp(/WITHIN\s+([-+]?[0-9]*\.?[0-9]+)\s+OF/i, 1).map((x: any) => parseFloat(x)),
         map: (radius: number, selection: Expression) => {
             return B.struct.modifier.includeSurroundings({ 0: selection, radius });
         }
@@ -40,7 +40,7 @@ export const operators: OperatorList = [
         '@examples': ['exwithin 10 of resname HEM'],
         name: 'exwithin',
         type: h.prefix,
-        rule: h.prefixOp(/EXWITHIN\s+([-+]?[0-9]*\.?[0-9]+)\s+OF/i, 1).map((x:any) => parseFloat(x)),
+        rule: h.prefixOp(/EXWITHIN\s+([-+]?[0-9]*\.?[0-9]+)\s+OF/i, 1).map((x: any) => parseFloat(x)),
         map: (radius: number, target: Expression) => {
             return B.struct.modifier.exceptBy({
                 '0': B.struct.filter.within({
@@ -55,7 +55,7 @@ export const operators: OperatorList = [
         '@examples': ['same resid as name FE'],
         name: 'same',
         type: h.prefix,
-        rule: h.prefixOp(new RegExp(`SAME\\s+(${propNames})\\s+AS`, 'i'), 1).map((x:any) => properties[x].property),
+        rule: h.prefixOp(new RegExp(`SAME\\s+(${propNames})\\s+AS`, 'i'), 1).map((x: any) => properties[x].property),
         map: (property: Expression, source: Expression) => {
             return B.struct.filter.withSameAtomProperties({
                 '0': B.struct.generator.atomGroups(),

+ 16 - 17
src/mol-script/transpilers/vmd/parser.ts

@@ -112,7 +112,7 @@ const valueOperators: OperatorList = [
 ];
 
 const lang = P.MonadicParser.createLanguage({
-    Parens: function (r:any) {
+    Parens: function (r: any) {
         return P.MonadicParser.alt(
             r.Parens,
             r.Operator,
@@ -120,7 +120,7 @@ const lang = P.MonadicParser.createLanguage({
         ).wrap(P.MonadicParser.string('('), P.MonadicParser.string(')'));
     },
 
-    Expression: function (r:any) {
+    Expression: function (r: any) {
         return P.MonadicParser.alt(
             r.RangeListProperty,
 	    r.NamedAtomProperties,
@@ -135,7 +135,7 @@ const lang = P.MonadicParser.createLanguage({
 
     Keywords: () => P.MonadicParser.alt(...h.getKeywordRules(keywords)),
 
-    ValueRange: function (r:any) {
+    ValueRange: function (r: any) {
         return P.MonadicParser.seq(
             r.Value
                 .skip(P.MonadicParser.regexp(/\s+TO\s+/i)),
@@ -143,7 +143,7 @@ const lang = P.MonadicParser.createLanguage({
         ).map(x => ({ range: x }));
     },
 
-    RangeListProperty: function (r:any) {
+    RangeListProperty: function (r: any) {
         return P.MonadicParser.seq(
             P.MonadicParser.alt(...h.getPropertyNameRules(properties, /\s/))
                 .skip(P.MonadicParser.whitespace),
@@ -156,7 +156,7 @@ const lang = P.MonadicParser.createLanguage({
             const listValues: (string | number)[] = [];
             const rangeValues: any[] = [];
 
-            values.forEach((v:any) => {
+            values.forEach((v: any) => {
                 if (v.range) {
                     rangeValues.push(
                         B.core.rel.inRange([property, v.range[0], v.range[1]])
@@ -178,16 +178,16 @@ const lang = P.MonadicParser.createLanguage({
 
 	    //  return B.struct.generator.atomGroups({ [h.testLevel(property)]: test });
 	    //  h.testLevel is not working for unknown reason, so relaced it by hardcoded 'atom-test'
-//	    console.log(h.testLevel(property));
+            //	    console.log(h.testLevel(property));
 	    return B.struct.generator.atomGroups({ 'atom-test': test });
         });
     },
 
-    Operator: function (r:any) {
+    Operator: function (r: any) {
         return h.combineOperators(operators, P.MonadicParser.alt(r.Parens, r.Expression, r.ValueQuery));
     },
 
-    Query: function (r:any) {
+    Query: function (r: any) {
         return P.MonadicParser.alt(
             r.Operator,
             r.Parens,
@@ -207,15 +207,15 @@ const lang = P.MonadicParser.createLanguage({
         return P.MonadicParser.alt(
             P.MonadicParser.regexp(new RegExp(`(?!(${w}))[A-Z0-9_]+`, 'i')),
             P.MonadicParser.regexp(/'((?:[^"\\]|\\.)*)'/, 1),
-            P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map((x:any) => B.core.type.regex([`^${x}$`, 'i']))
+            P.MonadicParser.regexp(/"((?:[^"\\]|\\.)*)"/, 1).map((x: any) => B.core.type.regex([`^${x}$`, 'i']))
         ).desc('string');
     },
 
-    Value: function (r:any) {
+    Value: function (r: any) {
         return P.MonadicParser.alt(r.Number, r.String);
     },
 
-    ValueParens: function (r:any) {
+    ValueParens: function (r: any) {
         return P.MonadicParser.alt(
             r.ValueParens,
             r.ValueOperator,
@@ -227,11 +227,11 @@ const lang = P.MonadicParser.createLanguage({
         return P.MonadicParser.alt(...h.getPropertyNameRules(properties, /=~|==|>=|<=|=|!=|>|<|\)|\s|\+|-|\*|\//i));
     },
 
-    ValueOperator: function (r:any) {
+    ValueOperator: function (r: any) {
         return h.combineOperators(valueOperators, P.MonadicParser.alt(r.ValueParens, r.ValueExpressions));
     },
 
-    ValueExpressions: function (r:any) {
+    ValueExpressions: function (r: any) {
         return P.MonadicParser.alt(
             r.ValueFunctions,
             r.Value,
@@ -239,13 +239,13 @@ const lang = P.MonadicParser.createLanguage({
         );
     },
 
-    ValueFunctions: function (r:any) {
+    ValueFunctions: function (r: any) {
         return P.MonadicParser.alt(...h.getFunctionRules(functions, r.ValueOperator));
     },
 
-    ValueQuery: function (r:any) {
+    ValueQuery: function (r: any) {
         return P.MonadicParser.alt(
-            r.ValueOperator.map((x:any) => {
+            r.ValueOperator.map((x: any) => {
                 // if (!x.head || x.head.startsWith('core.math') || x.head.startsWith('structure-query.atom-property')) {
                 if (!x.head || !x.head.startsWith('structure-query.generator')) {
                     throw new Error(`values must be part of an comparison, value '${x}'`);
@@ -258,4 +258,3 @@ const lang = P.MonadicParser.createLanguage({
 });
 
 export const transpiler: Transpiler = str => lang.Query.tryParse(str);
-export default transpiler

+ 26 - 26
src/mol-util/monadic-parser.ts

@@ -8,8 +8,8 @@
  * Copyright (c) 2011-present J. Adkisson (http://jneen.net).
  */
 /**
-*  @author Koya Sakuma 
-*  implementation of seqMap for mol-script/transpiler/helper.ts 
+*  @author Koya Sakuma
+*  implementation of seqMap for mol-script/transpiler/helper.ts
 **/
 
 export class MonadicParser<A> {
@@ -23,7 +23,7 @@ export class MonadicParser<A> {
         return { success: false, index: makeLineColumnIndex(input, result.furthest), expected: result.expected };
     };
 
-    
+
     tryParse(str: string) {
         const result = this.parse(str);
         if (result.success) {
@@ -239,17 +239,17 @@ export namespace MonadicParser {
 
     export type Result<T> = Success<T> | Failure
 
-    
-    export function seqMap( a: MonadicParser<any>,b:MonadicParser<any>,c:any) {
-	var args = [].slice.call(arguments);
-	if (args.length === 0) {
-	    throw new Error("seqMap needs at least one argument");
-	}
-	var mapper = args.pop();
-	assertFunction(mapper);
-	return seq.apply(null, args).map(function(results: any) {
+
+    export function seqMap(a: MonadicParser<any>, b: MonadicParser<any>, c: any) {
+        const args = [].slice.call(arguments);
+        if (args.length === 0) {
+	    throw new Error('seqMap needs at least one argument');
+        }
+        const mapper = args.pop();
+        assertFunction(mapper);
+        return seq.apply(null, args).map(function (results: any) {
 	    return mapper.apply(null, results);
-	});
+        });
     }
 
     export function createLanguage(parsers: any) {
@@ -262,7 +262,7 @@ export namespace MonadicParser {
         return language;
     }
 
-    
+
     export function seq<A>(a: MonadicParser<A>): MonadicParser<[A]>
     export function seq<A, B>(a: MonadicParser<A>, b: MonadicParser<B>): MonadicParser<[A, B]>
     export function seq<A, B, C>(a: MonadicParser<A>, b: MonadicParser<B>, c: MonadicParser<C>): MonadicParser<[A, B, C]>
@@ -342,11 +342,11 @@ export namespace MonadicParser {
         return RegExp('^(?:' + re.source + ')', flags(re));
     }
 
-   
+
     export function regexp(re: RegExp, group = 0) {
         const anchored = anchoredRegexp(re);
         const expected = '' + re;
-        return new MonadicParser<any>( function (input:any, i:any){
+        return new MonadicParser<any>(function (input: any, i: any) {
             const match = anchored.exec(input.slice(i));
             if (match) {
                 if (0 <= group && group <= match.length) {
@@ -368,7 +368,7 @@ export namespace MonadicParser {
     export function fail(expected: string): MonadicParser<any> {
         return new MonadicParser((input, i) => makeFailure(i, expected));
     }
-    
+
     export function lookahead<A>(x: MonadicParser<A> | string | RegExp): MonadicParser<null> {
         if (isParser(x)) {
             return new MonadicParser((input, i) => {
@@ -476,14 +476,14 @@ export namespace MonadicParser {
     export const newline = alt(crlf, lf, cr).desc('newline');
     export const end = alt(newline, eof);
 
-    export function of(A:any){
-	return succeed(A);
+    export function of(A: any) {
+        return succeed(A);
     }
 
-    export function regex(A:any){
-	return regexp(A);
+    export function regex(A: any) {
+        return regexp(A);
     }
-    
+
     MonadicParser.createLanguage = createLanguage;
     MonadicParser.seq = seq;
     MonadicParser.seqMap = seqMap;
@@ -491,7 +491,7 @@ export namespace MonadicParser {
     MonadicParser.regex = regexp;
     MonadicParser.regexp = regexp;
 //    MonadicParser.regexp.lookahead = lookahead;
-    //MonadicParser.RegExp = regexp;
+    // MonadicParser.RegExp = regexp;
 }
 
 function seqPick(idx: number, ...parsers: MonadicParser<any>[]): MonadicParser<any> {
@@ -589,9 +589,9 @@ function isParser(obj: any): obj is MonadicParser<any> {
     return obj instanceof MonadicParser;
 }
 
-function assertFunction(x:any) {
-    if (typeof x !== "function") {
-	throw new Error("not a function: " + x);
+function assertFunction(x: any) {
+    if (typeof x !== 'function') {
+        throw new Error('not a function: ' + x);
     }
 }
 

Some files were not shown because too many files changed in this diff