Sublime Forum

How to run external exe with args and get output?

#1

I recently started write a plugin that should run a third-party console program with parameters, and then show output log of this program.
For example:
in console I write this: clang --analyze main.c -DSTM32F10X_MD_VL
in this case output will be: main.c:20:2: error: called object type 'uint32_t' (aka 'unsigned int') is not a function or function pointer GPIOC->CRH &= ~(GPIO_CRH_MODE8); ^ ./stm32f10x.h:1410:29: note: expanded from macro 'GPIOC' #define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) ^ main.c:49:2: error: called object type 'uint32_t' (aka 'unsigned int') is not a function or function pointer GPIOA->CRL |= GPIO_CRL_CNF0_1; ^ ./stm32f10x.h:1408:29: note: expanded from macro 'GPIOA' #define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) ^ 2 errors generated.

So, in my plugin I need to run “clang --analyze main.c -DSTM32F10X_MD_VL”, and after that get output to the text buffer. I find sublime.run_command(string, ), but it ran just ApplicationCommand, but I need run global windows command to execute program in background to Sublime Text.
How can I do this?

0 Likes

#2

I’m not entirely sure if I understand, but take a look at the “exec” command: docs.sublimetext.info/en/latest/ … /exec.html

0 Likes

#3

Maybe you are right, but I try to write this:

import sublime, sublime_plugin class ClangCommand(sublime_plugin.TextCommand): def run(self, edit): self.run_command('exec', {'cmd': 'clang', '--analyze', 'main.c'], 'working_dir': 'P:\4 electronics\soft\Sublime Text projects\STM32F1-test0-GPIO\source\user-code'], 'shell':True} )

And get error in Sublime Text Console: self.run_command('exec', {'cmd': 'clang', '--analyze', 'main.c'], 'working_dir': 'P:\4 electronics\soft\Sublime Text projects\STM32F1-test0-GPIO\source\user-code', 'shell':True} ) ^ SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 69-70: truncated \uXXXX escape
What is wrong with the syntax?

0 Likes

#4

You are not escaping backslashes in Python strings. You can circumvent the requirement of backslash-escaping by declaring the string as a raw string, such as follows: r'P:\path\to\file', or just use normal escape sequences: 'P:\\path\\to\\file'.

0 Likes

#5

I changed code like you say. Now it works! Thanks. import sublime, sublime_plugin class ClangCommand(sublime_plugin.WindowCommand): def run(self): self.window.run_command('exec', {'cmd': 'clang', '--analyze', 'main.c', '-DSTM32F10X_MD_VL'], 'working_dir': r'P:\4 electronics\soft\Sublime Text projects\STM32F1-test0-GPIO\source\user-code', 'shell':True} )
I create test simple project and made in it one simple mistake. Now when I write: window.run_command('clang') I get output panel with output log with information about the errors in C/C++:

main.c:30:2: error: called object type 'uint32_t' (aka 'unsigned int') is not a function or function pointer GPIOC->CRH &= ~(GPIO_CRH_CNF9); ^ ./stm32f10x.h:1410:29: note: expanded from macro 'GPIOC' #define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) ^ 1 error generated. [Finished in 0.1s with exit code 1] [cmd: ['clang', '--analyze', 'main.c', '-DSTM32F10X_MD_VL']] [dir: P:\4 electronics\soft\Sublime Text projects\STM32F1-test0-GPIO\source\user-code]apath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wb...
Excellent!
Now I will try to understand how to get the information from this log, and what to do so it would not appear every time when I call this command.

0 Likes

#6

As it turned out “self.window.run_command(‘exec’, {‘cmd’: …” - this is not exactly what I need, because it does not allow to run third-party program in a separate thread in the background.

What I need is implemented in the code that I posted below:

[code]import sublime, sublime_plugin
import subprocess
class ClangCommand(sublime_plugin.TextCommand):
def run(self, edit):
cmd = ‘clang’, ‘–analyze’, ‘main.c’, ‘-DSTM32F10X_MD_VL’, r’-IP:\4 electronics\soft\Sublime Text projects\STM32F1-test0-GPIO\source\user-code’]
startupinfo = subprocess.STARTUPINFO()

	p = subprocess.Popen(cmd,
						bufsize = -1,
						cwd = r'P:\4 electronics\soft\Sublime Text projects\STM32F1-test0-GPIO\source\user-code',
						stdin=subprocess.PIPE,
						stdout=subprocess.PIPE,
						stderr=subprocess.PIPE,
						startupinfo=startupinfo,
						shell=True,
						creationflags=subprocess.SW_HIDE)
	
	output, stderr = p.communicate()
	
	if (stderr):
		print(stderr)
	print(output)

[/code]
The result of this program is displayed in the Sublime Text console.

0 Likes

#7

Yes, if you want to process the other process’s output you’ll have to run it yourself. That’s what exec does internally anyway.

0 Likes