Skip to content

Commit 197e927

Browse files
authored
Merge pull request #5 from ZitRos/master
Ability to Compile a Class + Minor Enhancements
2 parents bd93e5e + 5d944f3 commit 197e927

File tree

5 files changed

+186
-40
lines changed

5 files changed

+186
-40
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
node_modules/
1+
node_modules/
2+
.idea
3+
*.iml

README.md

Lines changed: 0 additions & 18 deletions
This file was deleted.

cos.js

Lines changed: 123 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
21
const vscode = require('vscode')
32
const workspace = vscode.workspace
43
const window = vscode.window
54
const API = require('cos-api4node')
65
const fs = require('fs')
6+
const pkg = require('./package.json')
7+
8+
const COS_LANG_IDS = pkg[ 'contributes' ][ 'languages' ].map( lang => lang.id )
79

810
const createBar = () => {
911

@@ -23,20 +25,129 @@ const activate = context => {
2325

2426
const output = window.createOutputChannel( 'cos' )
2527

26-
const log = msg => output.appendLine( msg )
28+
const log = msg => {
29+
output.appendLine( msg )
30+
return true
31+
}
2732

2833
const conn = workspace.getConfiguration( 'cos' ).get( 'conn' )
2934

3035
const api = API( conn )
3136

3237
api.headServer( ( err ) => {
3338

34-
if ( !!err ) return log( 'connect FAIL' )
35-
log( 'connected ' + JSON.stringify( conn ) )
39+
const connectionParameters = JSON.stringify(
40+
Object.assign({}, conn, {
41+
password: "***"
42+
}),
43+
null,
44+
4
45+
);
46+
if ( !!err ) return log( 'Connection FAILED: ' + connectionParameters )
47+
log( 'Connected ' + connectionParameters )
3648
bar.set( conn )
3749

3850
})
51+
52+
/**
53+
* Import and compile current file.
54+
*/
55+
const cosCompile = () => {
56+
57+
if ( !window.activeTextEditor )
58+
return log( 'No active editor, open one at first' )
59+
60+
const openedDoc = window.activeTextEditor.document
61+
62+
if ( !openedDoc )
63+
return log( 'Open a Caché ObjectScript file first.' )
64+
65+
const fileName = openedDoc.fileName;
66+
67+
if ( !fileName || COS_LANG_IDS.indexOf(openedDoc.languageId) === -1 )
68+
return log( `Document ${ fileName } cannot be compiled in Caché (type ${ openedDoc.languageId } unsupported)` )
69+
70+
log( `Saving ${ fileName }...` )
71+
72+
let cacheDocName;
73+
const fileBody = openedDoc.getText()
74+
const isClass = /\.cls$/i.test( fileName )
75+
const content = fileBody.split( /\r?\n/g )
76+
77+
if ( isClass ) {
78+
// Caché class files can be placed hierarchically (e.g. /src/Package/Class.cls),
79+
// so we pick the class name from the class definition itself
80+
cacheDocName = (fileBody.replace( /\/\/[^\r\n]*\r?\n/g, '' ).match( /Class ([^\s]+)/i ) || [])[ 1 ] || ""
81+
const nameParts = cacheDocName.split( /\./g ).filter(s => !!s)
82+
if ( nameParts.length < 2 )
83+
return log( `Unable to detect class name in source code of ${ fileName }.\n`
84+
+ `Is it a valid Caché ObjectScript class?` )
85+
const matchingFileName = ( fileName.match(/[^\\\/]+$/) || [] )[ 0 ]
86+
if ( ( cacheDocName.toLowerCase() + '.cls' ).indexOf(matchingFileName.toLowerCase()) === -1 )
87+
return log( `You tried to compile class named "${ cacheDocName }" in file "${ matchingFileName }".\n`
88+
+ `Did you forget to rename the file/class to correspond to each other?` )
89+
cacheDocName += '.cls'
90+
} else {
91+
// routine: cacheDocName = actual filename
92+
cacheDocName = ( fileName.match( /[\\\/]([^\\\/]+)$/ ) || [] )[ 1 ] || ""
93+
}
94+
95+
const anyErrors = (err, res, keyword) => {
96+
97+
if ( err )
98+
return log( `Unable to ${ keyword } ${ cacheDocName }: ${ err.code ? err.code + ' ' + err.message : err }` )
99+
100+
if ( !res || !res.status || !(res.status.errors instanceof Array) )
101+
return log( `Unknown response from Atelier API while trying to ${
102+
keyword } ${ cacheDocName }: ${ res }` )
103+
104+
if ( res.result && res.result.status )
105+
return log( res.result.status )
106+
107+
if ( res.status.errors.length !== 0 )
108+
return log( `Unable to ${ keyword } ${ cacheDocName }: ${ res.status.errors.summary }\n\n${
109+
res.console }\n\n${ res.status.errors.join('\n') }` )
110+
111+
return false;
112+
113+
}
114+
115+
const consoleOutput = (output, defaultOutput = "") => {
116+
117+
let out = output instanceof Array
118+
? output.join( '\n' )
119+
: ( output || defaultOutput ) + '';
120+
out = out.replace( /^[\s\r\n]+/, '' );
121+
122+
if ( out ) {
123+
log( out )
124+
}
125+
126+
}
127+
128+
api.putDoc( cacheDocName, { enc: false, content }, { ignoreConflict: true }, ( err, res ) => {
129+
130+
if ( anyErrors( err, res, 'save' ) )
131+
return;
132+
133+
consoleOutput( res.console )
134+
135+
api.compile( cacheDocName, ( err, res ) => {
136+
137+
if ( anyErrors( err, res, 'compile' ) )
138+
return;
139+
140+
consoleOutput( res.console || "Done." )
141+
142+
} )
143+
144+
} )
145+
146+
}
39147

148+
/**
149+
* Export all classes/routines in a namespace to working directory.
150+
*/
40151
const cosExport = () => {
41152

42153
const exportDoc = ( doc, cb ) => {
@@ -64,7 +175,7 @@ const activate = context => {
64175

65176
const load = ( doc, cb ) => {
66177

67-
const loaded = ( err, data ) => {
178+
const loaded = ( err, json ) => {
68179

69180
if ( !!err ) {
70181

@@ -75,7 +186,6 @@ const activate = context => {
75186

76187
}
77188

78-
const json = JSON.parse( data )
79189
const content = json.result
80190
exportDoc( content, cb )
81191

@@ -96,18 +206,17 @@ const activate = context => {
96206
}
97207

98208

99-
const onGetDocs = ( err, data ) => {
209+
const onGetDocs = ( err, json ) => {
100210

101-
if ( err ) return log( 'getDocs ERROR')
211+
if ( err ) return log( 'getDocs ERROR' )
102212

103-
const json = JSON.parse( data )
104213
const list = json.result.content
105214
log( '' )
106215
log( 'list: ' + list.length )
107216
const docs = list.filter( doc => ( doc.cat !== 'CSP' ) && ( doc.name.substring( 0, 1 ) !== '%' ) && ( doc.name.substring( 0, 12 ) !== 'INFORMATION.' ) )
108217
log( 'without % and CSP and INFORMATION: ' + docs.length )
109218
log( '' )
110-
exportDocs( docs, ()=>{
219+
exportDocs( docs, () => {
111220
log( '' )
112221
log( 'Export completed.' )
113222
})
@@ -119,8 +228,10 @@ const activate = context => {
119228
}
120229

121230
// command 'cos.server' defined in statusBar
122-
const cmd = vscode.commands.registerCommand( 'cos.export', cosExport )
123-
context.subscriptions.push( cmd )
231+
context.subscriptions.push(
232+
vscode.commands.registerCommand( 'cos.export', cosExport ),
233+
vscode.commands.registerCommand( 'cos.compile', cosCompile )
234+
)
124235

125236
}
126237

package.json

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vscode-cos",
33
"displayName": "Caché ObjectScript",
44
"description": "Caché ObjectScript language support for Visual Studio Code",
5-
"version": "0.0.4",
5+
"version": "0.1.0",
66
"icon": "images/logo.png",
77
"categories": [
88
"Languages",
@@ -13,6 +13,9 @@
1313
"url": "https://github.com/doublefint/vscode-cos.git"
1414
},
1515
"publisher": "doublefint",
16+
"contributors": [
17+
{ "name": "Nikita Savchenko", "email": "[email protected]" }
18+
],
1619
"engines": {
1720
"vscode": "^1.5.0"
1821
},
@@ -24,17 +27,24 @@
2427
"languages": [
2528
{
2629
"id": "cachéobjectscript",
27-
"aliases": [ "COS" ],
28-
"extensions": [ ".cls" ],
30+
"aliases": [
31+
"COS"
32+
],
33+
"extensions": [
34+
".cls"
35+
],
2936
"configuration": "./language-configuration.json"
3037
},
3138
{
3239
"id": "cachéobjectscriptinclude",
33-
"aliases": [ "COS.INC" ],
34-
"extensions": [ ".inc" ],
40+
"aliases": [
41+
"COS.INC"
42+
],
43+
"extensions": [
44+
".inc"
45+
],
3546
"configuration": "./language-configuration.json"
3647
}
37-
3848
],
3949
"grammars": [
4050
{
@@ -50,11 +60,23 @@
5060
],
5161
"commands": [
5262
{
53-
"category": "cos",
63+
"category": "COS",
5464
"command": "cos.export",
55-
"title": "export sources"
65+
"title": "Export sources"
66+
},
67+
{
68+
"category": "COS",
69+
"command": "cos.compile",
70+
"title": "Import and compile current file"
5671
}
5772
],
73+
"keybindings": [
74+
{
75+
"command": "cos.compile",
76+
"key": "Ctrl+F7",
77+
"mac": "Cmd+F7"
78+
}
79+
],
5880
"configuration": {
5981
"title": "cos",
6082
"type": "object",
@@ -80,6 +102,6 @@
80102
"vscode": "^1.0.3"
81103
},
82104
"dependencies": {
83-
"cos-api4node": "^1.1.0"
105+
"cos-api4node": "^2.0.0"
84106
}
85107
}

readme.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# vscode-cos
2+
3+
Initial [Cache](http://www.intersystems.com/our-products/cache/cache-overview/) ObjectScript ( COS ) language support for Visual Studio Code
4+
5+
Features
6+
--------
7+
8+
![example](images/screenshot.png)
9+
10+
Configure connection
11+
--------------------
12+
13+
To be able to use many plugin features, you need to configure the connection to Caché server first.
14+
15+
- Find a 'cos.conn' section in workspace settings (File - Preferences - Settings)
16+
- change settings according to your Caché instance and reload VSCode ( as temporary solution )
17+
18+
Features
19+
--------
20+
21+
+ Export existing sources to the working directory: press Ctrl+Shift+P, type 'COS', press Enter.
22+
+ Save and compile a class: press Ctrl+F7 or select "COS: Save and compile" from Ctrl+Shift+P menu.
23+
24+
Notes
25+
-----
26+
27+
For Caché instance with maximum security level, add '%Development' role for '/api/atelier/' web-application ( [More]( https://community.intersystems.com/post/using-atelier-rest-api) )
28+
29+
Language support based on https://github.com/RustamIbragimov/atom-language-cos

0 commit comments

Comments
 (0)