@@ -15,8 +15,12 @@ import { getBinPath } from './util';
1515import vscode = require( 'vscode' ) ;
1616import { CommandFactory } from './commands' ;
1717
18- // Supports only passing interface, see TODO in implCursor to finish
19- const inputRegex = / ^ ( \w + \ \* ? \w + \ ) ? ( [ \w \. \- \/ ] + ) $ / ;
18+ // Accepts input of the form:
19+ // [f *File] io.Closer [, ...]
20+ // [f *File] io.Closer
21+ // io.Closer (type name will be deduced from variable name from cursor position)
22+ // io.Closer, io.Reader (same as above)
23+ const inputRegex = / ^ (?< identifier > (?< variable > [ \p{ Letter} _ ] [ \p{ Letter} _ \p{ Number} \d ] * ) * (?< type > [ * ] ? * [ \p{ Letter} _ ] [ \p{ Letter} _ \p{ Number} \d ] * ) + ) ? (?< interfaces > (?: [ \p{ Letter} _ ] [ \p{ Letter} _ \p{ Number} \d \. \- \/ ] * ) + (?: * , * (?: [ \p{ Letter} _ ] [ \p{ Letter} _ \p{ Number} \d \. \- \/ ] * ) + ) * ) $ / u;
2024
2125export const implCursor : CommandFactory = ( ) => ( ) => {
2226 const editor = vscode . window . activeTextEditor ;
@@ -27,50 +31,72 @@ export const implCursor: CommandFactory = () => () => {
2731 const cursor = editor . selection ;
2832 return vscode . window
2933 . showInputBox ( {
30- placeHolder : 'f *File io.Closer' ,
34+ placeHolder : '[ f *File] io.Closer [, ...] ' ,
3135 prompt : 'Enter receiver and interface to implement.'
3236 } )
3337 . then ( ( implInput ) => {
3438 if ( typeof implInput === 'undefined' ) {
3539 return ;
3640 }
3741 const matches = implInput . match ( inputRegex ) ;
38- if ( ! matches ) {
42+ if ( ! matches || ! matches . groups || ! matches . groups . interfaces ) {
3943 vscode . window . showInformationMessage ( `Not parsable input: ${ implInput } ` ) ;
4044 return ;
4145 }
4246
43- // TODO: automatically detect type name at cursor
44- // if matches[1] is undefined then detect receiver type
45- // take first character and use as receiver name
47+ let identifier = matches . groups ?. identifier ;
48+ if ( ! identifier ) {
49+ const beforeCursor = new vscode . Range ( new vscode . Position ( cursor . start . line , 0 ) , cursor . start ) ;
50+ const beforeCursorText = editor . document . getText ( beforeCursor ) ;
51+ const typeIndex = beforeCursorText . lastIndexOf ( 'type' ) ;
52+ if ( typeIndex === - 1 ) {
53+ vscode . window . showInformationMessage ( 'No identifier found at cursor.' ) ;
54+ return ;
55+ }
4656
47- runGoImpl ( [ matches [ 1 ] , matches [ 2 ] ] , cursor . start , editor ) ;
57+ const variable = editor . document . getText ( cursor ) [ 0 ] . toLowerCase ( ) ;
58+ identifier = editor . document . getText ( cursor ) ;
59+ identifier = `${ variable } *${ identifier } ` ;
60+
61+ let newPosition = cursor . start . with ( cursor . start . line + 1 , 0 ) ;
62+ newPosition = newPosition . translate ( 1 , 0 ) ;
63+ editor . selection = new vscode . Selection ( newPosition , newPosition ) ;
64+ }
65+ const interfaces = matches . groups ?. interfaces . trim ( ) . split ( ',' ) ;
66+ interfaces . forEach ( ( iface , i ) => {
67+ interfaces [ i ] = iface . trim ( ) ;
68+ } ) ;
69+ runGoImpl ( [ identifier , interfaces ] , editor ) ;
4870 } ) ;
4971} ;
5072
51- function runGoImpl ( args : string [ ] , insertPos : vscode . Position , editor : vscode . TextEditor ) {
73+ function runGoImpl ( prompt : [ string , string [ ] ] , editor : vscode . TextEditor ) {
5274 const goimpl = getBinPath ( 'impl' ) ;
53- const p = cp . execFile (
54- goimpl ,
55- args ,
56- { env : toolExecutionEnvironment ( ) , cwd : dirname ( editor . document . fileName ) } ,
57- ( err , stdout , stderr ) => {
58- if ( err && ( < any > err ) . code === 'ENOENT' ) {
59- promptForMissingTool ( 'impl' ) ;
60- return ;
61- }
75+ prompt [ 1 ] . forEach ( ( iface ) => {
76+ const p = cp . execFile (
77+ goimpl ,
78+ [ prompt [ 0 ] , iface ] ,
79+ { env : toolExecutionEnvironment ( ) , cwd : dirname ( editor . document . fileName ) } ,
80+ ( err , stdout , stderr ) => {
81+ if ( err && ( < any > err ) . code === 'ENOENT' ) {
82+ promptForMissingTool ( 'impl' ) ;
83+ return ;
84+ }
6285
63- if ( err ) {
64- vscode . window . showInformationMessage ( `Cannot stub interface: ${ stderr } ` ) ;
65- return ;
66- }
86+ if ( err ) {
87+ vscode . window . showInformationMessage ( `Cannot stub interface: ${ stderr } ` ) ;
88+ return ;
89+ }
6790
68- editor . edit ( ( editBuilder ) => {
69- editBuilder . insert ( insertPos , stdout ) ;
70- } ) ;
91+ ( function ( out : string ) {
92+ editor . edit ( ( editBuilder ) => {
93+ editBuilder . insert ( editor . selection . start , out ) ;
94+ } ) ;
95+ } ) ( stdout ) ;
96+ }
97+ ) ;
98+ if ( p . pid ) {
99+ p . stdin ?. end ( ) ;
71100 }
72- ) ;
73- if ( p . pid ) {
74- p . stdin ?. end ( ) ;
75- }
101+ } ) ;
76102}
0 commit comments