Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9535d38

Browse files
committed
migrate files from vc-react
1 parenta76e3bb commit9535d38

21 files changed

+970
-18
lines changed

‎src/commands/index.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import*asvscodefrom'vscode'
2+
3+
importrunTestfrom'./runTest'
4+
importtutorialLoadfrom'./tutorialLoad'
5+
importloadSolutionfrom'./loadSolution'
6+
// import quit from './quit'
7+
8+
constCOMMANDS={
9+
RUN_TEST:'coderoad.test_run',
10+
TUTORIAL_LOAD:'coderoad.tutorial_load',
11+
TUTORIAL_SETUP:'coderoad.tutorial_setup',
12+
LOAD_SOLUTION:'coderoad.solution_load',
13+
// QUIT: 'coderoad.quit',
14+
}
15+
16+
exportdefault(context:vscode.ExtensionContext):void=>{
17+
constcommands={
18+
[COMMANDS.TUTORIAL_LOAD]():void{
19+
tutorialLoad(context)
20+
},
21+
[COMMANDS.RUN_TEST]:runTest,
22+
[COMMANDS.LOAD_SOLUTION]:loadSolution,
23+
// [COMMANDS.QUIT]: () => quit(context.subscriptions),
24+
}
25+
26+
for(constcmdincommands){
27+
constcommand:vscode.Disposable=vscode.commands.registerCommand(cmd,commands[cmd])
28+
context.subscriptions.push(command)
29+
}
30+
}

‎src/commands/loadSolution.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import*asCRfrom'typings'
2+
import*asstoragefrom'../services/storage'
3+
import{gitLoadCommits,gitClear}from'../services/git'
4+
5+
exportdefaultasyncfunctionloadSolution():Promise<void>{
6+
const[position,tutorial]:[CR.Position,CR.Tutorial|undefined]=awaitPromise.all([
7+
storage.getPosition(),
8+
storage.getTutorial(),
9+
])
10+
if(!position){
11+
thrownewError('No tutorial position state found')
12+
}
13+
if(!tutorial){
14+
thrownewError('Local tutorial not found')
15+
}
16+
// eslint-disable-next-line
17+
const{ solution}=tutorial.data.steps[position.stepId].actions
18+
19+
awaitgitClear()
20+
awaitgitLoadCommits(solution)
21+
}

‎src/commands/quit.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import*asvscodefrom'vscode'
2+
3+
exportdefault()=>{
4+
// TODO: quit
5+
}

‎src/commands/runTest.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import{getOutputChannel}from'../utils/channel'
2+
import{exec}from'../utils/node'
3+
import*asstoragefrom'../services/storage'
4+
import*astestResultfrom'../services/testResult'
5+
6+
// ensure only latest run_test action is taken
7+
letcurrentId=0
8+
9+
// quick solution to prevent processing multiple results
10+
// NOTE: may be possible to kill child process early
11+
constshouldExitEarly=(processId:number):boolean=>{
12+
returncurrentId!==processId
13+
}
14+
15+
exportdefaultasyncfunctionrunTest():Promise<void>{
16+
// increment process id
17+
letprocessId=++currentId
18+
19+
constoutputChannelName='Test Output'
20+
21+
// TODO: validate test directory from package.json exists
22+
// let testFile = path.join('test');
23+
// if (!await exists(testFile)) {
24+
// return emptyTasks;
25+
// }
26+
27+
// TODO: verify test runner for args
28+
consttestArgs=['--json']
29+
30+
// if .git repo, use --onlyChanged
31+
// const hasGit = path.join('.git');
32+
// if (await exists(hasGit)) {
33+
// testArgs.push('--onlyChanged')
34+
// }
35+
36+
letcommandLine=`npm test --${testArgs.join(' ')}`
37+
38+
try{
39+
// capture position early on test start
40+
// in case position changes
41+
const[position,{ stdout}]=awaitPromise.all([storage.getPosition(),exec(commandLine)])
42+
if(shouldExitEarly(processId)){
43+
// exit early
44+
return
45+
}
46+
47+
if(stdout){
48+
letlines=stdout.split(/\r{0,1}\n/)
49+
console.log('SUCCESS LINES',lines)
50+
for(letlineoflines){
51+
if(line.length===0){
52+
continue
53+
}
54+
55+
constregExp=/^{\"numFailedTestSuites/
56+
constmatches=regExp.exec(line)
57+
if(matches&&matches.length){
58+
console.log('MATCHES SUCCESS')
59+
constresult=JSON.parse(line)
60+
61+
if(result.success){
62+
console.log('SUCCESS')
63+
if(shouldExitEarly(processId)){
64+
// exit early
65+
return
66+
}
67+
//@ts-ignore
68+
testResult.onSuccess(position)
69+
}else{
70+
console.log('NOT SUCCESS?')
71+
}
72+
}
73+
}
74+
}
75+
}catch(err){
76+
if(shouldExitEarly(processId)){
77+
// exit early
78+
return
79+
}
80+
// error contains output & error message
81+
// output can be parsed as json
82+
const{ stdout, stderr}=err
83+
console.log('TEST FAILED',stdout)
84+
85+
if(!stdout){
86+
console.error('SOMETHING WENT WRONG WITH A PASSING TEST')
87+
}
88+
// test runner failed
89+
constchannel=getOutputChannel(outputChannelName)
90+
91+
if(stdout){
92+
letlines=stdout.split(/\r{0,1}\n/)
93+
94+
for(letlineoflines){
95+
if(line.length===0){
96+
continue
97+
}
98+
99+
constdataRegExp=/^{\"numFailedTestSuites"/
100+
constmatches=dataRegExp.exec(line)
101+
102+
if(matches&&matches.length){
103+
constresult=JSON.parse(line)
104+
constfirstError=result.testResults.find((t:any)=>t.status==='failed')
105+
106+
if(firstError){
107+
if(shouldExitEarly(processId)){
108+
// exit early
109+
return
110+
}
111+
console.log('ERROR',firstError.message)
112+
testResult.onFailure()
113+
}else{
114+
console.error('NOTE: PARSER DID NOT WORK FOR ',line)
115+
}
116+
}
117+
}
118+
}
119+
120+
if(stderr){
121+
channel.show(false)
122+
channel.appendLine(stderr)
123+
}
124+
// if (err.stdout) {
125+
// channel.appendLine(err.stdout);
126+
// }
127+
}
128+
}

‎src/commands/tutorialLoad.ts

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import*asvscodefrom'vscode'
2+
import*asCRfrom'typings'
3+
4+
importfetchfrom'../utils/fetch'
5+
importtutorialSetupfrom'../services/tutorialSetup'
6+
import{loadProgressPosition}from'../services/position'
7+
import*asstoragefrom'../services/storage'
8+
importrootSetupfrom'../services/rootSetup'
9+
import{isEmptyWorkspace,openReadme}from'../utils/workspace'
10+
import*asgitfrom'../services/git'
11+
12+
/*
13+
new
14+
if current workspace is empty, use it
15+
if not, open a new folder then start
16+
*/
17+
18+
asyncfunctioncontinueTutorial(){
19+
// TODO: verify that tutorial is loaded in workspace
20+
// TODO: verify progress
21+
// TODO: verify setup
22+
awaitloadProgressPosition()
23+
awaitopenReadme()
24+
}
25+
26+
asyncfunctionnewTutorial(tutorial:CR.Tutorial){
27+
// if workspace isn't empty, clear it out if given permission
28+
constisEmpty:boolean=awaitisEmptyWorkspace()
29+
if(!isEmpty){
30+
// eslint-disable-next-line
31+
constoptions=['Open a new folder','I\'ll clear the files and folders myself']
32+
constshouldOpenFolder=awaitvscode.window.showQuickPick(options)
33+
if(shouldOpenFolder===options[0]){
34+
awaitvscode.commands.executeCommand('vscode.openFolder')
35+
}
36+
}
37+
38+
awaittutorialSetup(tutorial)
39+
awaitopenReadme()
40+
}
41+
42+
functiononSaveHook(languageIds:string[]){
43+
// trigger command on save
44+
vscode.workspace.onDidSaveTextDocument((document:vscode.TextDocument)=>{
45+
if(languageIds.includes(document.languageId)&&document.uri.scheme==='file'){
46+
// do work
47+
vscode.commands.executeCommand('coderoad.test_run')
48+
}
49+
})
50+
}
51+
52+
asyncfunctionvalidateCanContinue():Promise<boolean>{
53+
// validate tutorial & progress found in local storage
54+
// validate git is setup with a remote
55+
const[tutorial,progress,hasGit,hasGitRemote]=awaitPromise.all([
56+
storage.getTutorial(),
57+
storage.getProgress(),
58+
git.gitVersion(),
59+
git.gitCheckRemoteExists(),
60+
])
61+
return!!(tutorial&&progress&&hasGit&&hasGitRemote)
62+
}
63+
64+
exportdefaultasyncfunctiontutorialLoad(context:vscode.ExtensionContext):Promise<void>{
65+
// setup connection to workspace
66+
awaitrootSetup(context)
67+
68+
constmodes=['New']
69+
70+
constcanContinue=awaitvalidateCanContinue()
71+
if(canContinue){
72+
modes.push('Continue')
73+
}
74+
75+
constselectedMode:string|undefined=awaitvscode.window.showQuickPick(modes)
76+
77+
if(!selectedMode){
78+
thrownewError('No mode selected')
79+
return
80+
}
81+
82+
interfaceTutorialQuickPickItemextendsvscode.QuickPickItem{
83+
id:string
84+
}
85+
86+
// load tutorial summaries
87+
consttutorialsData:{[id:string]:CR.TutorialSummary}=awaitfetch({
88+
resource:'getTutorialsSummary',
89+
})
90+
constselectableTutorials:TutorialQuickPickItem[]=Object.keys(tutorialsData).map(id=>{
91+
consttutorial=tutorialsData[id]
92+
return{
93+
label:tutorial.title,
94+
description:tutorial.description,
95+
// detail: '', // optional additional info
96+
id,
97+
}
98+
})
99+
constselectedTutorial:TutorialQuickPickItem|undefined=awaitvscode.window.showQuickPick(selectableTutorials)
100+
101+
if(!selectedTutorial){
102+
thrownewError('No tutorial selected')
103+
}
104+
105+
// load specific tutorial
106+
consttutorial:CR.Tutorial|undefined=awaitfetch({
107+
resource:'getTutorial',
108+
params:{id:selectedTutorial.id},
109+
})
110+
111+
if(!tutorial){
112+
thrownewError('No tutorial found')
113+
}
114+
115+
switch(selectedMode){
116+
// new tutorial
117+
casemodes[0]:
118+
awaitnewTutorial(tutorial)
119+
break
120+
// continue
121+
casemodes[1]:
122+
awaitcontinueTutorial()
123+
break
124+
}
125+
126+
// setup hook to run tests on save
127+
onSaveHook(tutorial.meta.languages)
128+
129+
// TODO: start
130+
}

‎src/extension.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,28 @@
22
// Import the module and reference it with the alias vscode in your code below
33
import*asvscodefrom'vscode'
44

5+
importcreateCommandsfrom'./commands'
6+
importcreateViewsfrom'./views'
7+
58
// this method is called when your extension is activated
69
// your extension is activated the very first time the command is executed
710
exportfunctionactivate(context:vscode.ExtensionContext){
811

9-
// Use the console to output diagnostic information (console.log) and errors (console.error)
10-
// This line of code will only be executed once when your extension is activated
11-
console.log('Congratulations, your extension "coderoad-vscode" is now active!')
12-
13-
// The command has been defined in the package.json file
14-
// Now provide the implementation of the command with registerCommand
15-
// The commandId parameter must match the command field in package.json
16-
letdisposable=vscode.commands.registerCommand('extension.helloWorld',()=>{
17-
// The code you place here will be executed every time your command is executed
12+
// commands
13+
createCommands(context)
1814

19-
// Display a message box to the user
20-
vscode.window.showInformationMessage('Hello You!')
21-
})
15+
// tasks
16+
// add tasks here
2217

23-
context.subscriptions.push(disposable);
18+
// views
19+
createViews(context)
2420
}
2521

2622
// this method is called when your extension is deactivated
27-
exportfunctiondeactivate(){}
23+
exportfunctiondeactivate(context:vscode.ExtensionContext):void{
24+
// cleanup subscriptions/tasks
25+
console.log('deactivate context',context)
26+
for(constdisposableofcontext.subscriptions){
27+
disposable.dispose()
28+
}
29+
}

‎src/services/fs.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import{exec}from'../utils/node'
2+
3+
exportasyncfunctionclear():Promise<void>{
4+
// remove all files including ignored
5+
// NOTE: Linux only
6+
constcommand='ls -A1 | xargs rm -rf'
7+
const{ stderr}=awaitexec(command)
8+
if(stderr){
9+
console.error(stderr)
10+
thrownewError('Error removing all files & folders')
11+
}
12+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp