Default message when Build System starts in Sublime Text - sublimetext3

When you run Sublime Build and it finishes, there is a message [Finished ] (in the picture). I would like to add default message when every Build starts to be like "[Started]":
Also it would be nice to add local time when Build System started, e.g. [Started 22:20:23]

The are (at least) three ways to do this. The first way is to add the functionality to the beginning of your code, so it prints out the information you want. The disadvantage of this method is that the message is printed only when the code begins to run, not at the beginning of the build. Depending on the language you're using, whether it's compiled or interpreted, and the size of your codebase, this could be a significant lag.
The second method is to run your build through a shell file which executes using bash. On Windows, this requires that you have bash installed - Git Bash and Cygwin are two common ways of obtaining it. The following script accepts an arbitrary number of arguments, which it runs after printing "Started" and the date.
#!/bin/bash
echo "[Started at `date`]"
# check to see if we have at least 1 arg
if [ $1 ]
then
# replace this process w/ arg(s) so `exec.py` (the Sublime
# build system) gets the proper return value
exec "${#}"
fi
Save this file as build.sh somewhere in your PATH.
Now, take a look at the .sublime-build file for the build system you're using, specifically the "shell_cmd" or "cmd" line. If it's a "shell_cmd", all you'll need to do is copy and paste it (without the enclosing double quotes) into the build system below. If it's a "cmd", convert the array/list following "cmd": to a single string. So, for example, if you're using the default Python build system on Windows, "cmd": ["py", "-u", "$file"] would become py -u $file. Essentially, you're converting the array to what you would type at the command prompt, keeping Sublime-internal variables beginning with $ (like $file) intact.
Next, select Tools → Build System → New Build System…. Erase its contents and paste in the following template:
{
"shell_cmd": "bash -c \"build.sh new_cmd_goes_here\"",
"working_dir": "$file_path",
// "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
// "selector": "source.python",
// "env": {"PYTHONIOENCODING": "utf-8"}
}
replacing new_cmd_goes_here with the command string you just created in the step above. So, for our Python example, that line would become:
"shell_cmd": "bash -c \"build.sh py -u $file_name\"",
You can uncomment the commented-out lines in the build system template if you wish.
When you're done editing the build system, simply hit CtrlS to save, naming it something like Python (start message).sublime-build, for example. You don't need to change the directory the file is saved in, as Sublime will automatically put it in your Packages/User directory.
The third option is to modify Packages/Default/exec.py to fit your needs. This requires knowledge of Python and Sublime's internals. You can find the basics of how build systems work and how to extend them here.
Briefly, you would save Packages/Default/exec.py as Packages/User/exec_with_dt.py, setting the read_only flag to False if necessary. Next, change the name of the ExecCommand class to ExecWithDtCommand. Then, just after self.proc is defined as an AsyncProcess, add a line calling either self.append_string() (ST3) or self.write() (ST4) writing your desired string to the output. In ST4, I used:
from datetime import datetime as dt
self.write("[Started " + dt.now().strftime("%Y-%m-%d %H:%M:%S") + "]\n")
I haven't tested this in ST3, but the following should work there:
from datetime import datetime as dt
self.append_string(None, "[Started " + dt.now().strftime("%Y-%m-%d %H:%M:%S") + "]\n")
Save the file, then create a new build system with the following contents:
{
"target": "exec_with_dt",
"cmd": ["py", "-u", "$file"],
}
I don't recommend this approach unless you really know what you are doing, and the shell script method isn't sufficient for your needs. Other edits may need to be made to exec_with_dt.py to ensure complete parallel functionality with the original exec.py, so look through it carefully. For example, you may want to modify ExecEventListener to ExecWithDtEventListener and change its code to run the exec_with_dt command, just to keep everything in-house.

Related

Sublime 3 Path Variables

I am trying to set up a python 3 build path for sublime text 3 on a windows 10 pc. The system says that it cannot find the specified file, but I have already added the path and set the build system for python3. The error message I get when I try to build is below..
[WinError 2] The system cannot find the file specified
[cmd: ['python3', '-i', '-u', 'C:\\Users\\strinkjr\\Desktop\\Python Stuff\\errorSearch.py']]
[dir: C:\Users\strinkjr\Desktop\Python Stuff]
[path: C:\Users\strinkjr\Desktop\Python Stuff\]
[Finished]
My build environment file is as follows:
{
"cmd": ["python3", "-i", "-u", "$file"],
"file_regex": "^[ ]File \"C:/Users/strinkjr/AppData/Local/Programs/Python/Python36/python.exe\", line ([0-9]*)",
"selector": "source.python"
}
I am unsure if I set up the path incorrectly or if I set up the build environment incorrectly. (Maybe both)
There are a couple of overall problems you're having that are standing in your way here.
The first is that you didn't set the PATH correctly. The build output shows you the PATH as it's currently defined as far as the command execution is concerned:
[path: C:\Users\strinkjr\Desktop\Python Stuff\]
The PATH is the list of locations where windows will look for the program that you're trying to execute, so unless there is a python3.exe in this directory you've accidentally set the PATH to the location of the files that you're running and not the interpreter that's used to run them.
Secondly you're passing -i to the Python interpreter to get it to drop into interactive mode once it's done executing the script. Sublime doesn't let you interact with programs that you execute from within a sublime-build, so if you do this once your program finishes executing and goes into interactive mode, it's going to be effectively hung waiting for you to provide it input that you can't provide.
Your build system also contains this file_regex entry:
"file_regex": "^[ ]File \"C:/Users/strinkjr/AppData/Local/Programs/Python/Python36/python.exe\", line ([0-9]*)",
In a sublime-build file, the file_regex is used to be able to detect what lines in the program's output are errors so that Sublime can allow you to navigate between errors or flag them with inline errors if you have that option turned on.
Although this won't stop your programs from running, it will stop Sublime from being able to recognize errors because the name of the file is never going to match.
I would try a sublime-build file something like the following and see if that works better for you:
{
"shell_cmd": "python3 -u \"$file\"",
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python",
"env": {
"PYTHONIOENCODING": "utf-8",
"PATH": "$PATH;C:/Users/strinkjr/AppData/Local/Programs/Python/Python36/"
},
}
This removes the -i argument to stop the interpreter from going interactive in order to stop any problems and uses shell_cmd instead of cmd to provide the command, which changes the format slightly.
The file_regex here is one that will match regular python errors, which is similar to the one you already provided but without the reference to the Python executable.
The big addition here is a couple of environment variables. The first one ensures that Python knows that it should use utf-8 to generate output, since that's what the Sublime console is expecting it to use. That stops you from getting potential errors if you try to display non-ascii output.
This also applies a new PATH that includes the existing path and also adds to it the path that looks like it might be where your Python is installed based on the files you were already using.
That part may need adjustment if the location is not correct; alternatively you can remove the PATH portion of the sublime-build and modify your PATH environment variable as appropriate instead. Note that you may need to restart Sublime if you do that in order for it to see the change.

How can i use the variable in the path for source directory and destination using groovy

git1 repository have a folder named sports which further have subfolders and files inside it.I want to copy the file given by the output of git diff given by command2.
def command2 = "git diff --stat #{12.hours.ago}"
Process process = command2.execute(null, new File('C:/git1'))
def b=process.text
println b
Output of Groovy Console is Sports/Cricket/Players/Virat.txt.
Now i want to use this file path in sourceDir as shown below.
def sourceDir = "C:/git1/$b"
def destinationDir = "D:/git1/$b"
(new AntBuilder()).copy(file: sourceDir, tofile: destinationDir)
This is giving error as Warning: Could not find file C:\git1\Sports\Cricket\Players\Virat.txt
to copy.
As you can see in your comment with the byte array, the last character of the string is a newline character (10). This of course makes the path invalid but is not easily recognizable in the error message. Add a .trim() after the .text and it should work with both, AntBuilder and Files and on both, Windows and Linux. If you would have done it on Windows there would be a 13 additionally before the 10.
Another maybe even better approach would be not to use git diff as you do, as it is a porcelain command. Porcelain command as their name suggests are not stable and their arguments and output can change any time. They are meant for human usage, not for scripts. Scripts should use plumbing commands which are much more stable in input and output. With the respective plumbing command you might not have had your problem.

How to create Sublime Text 3 build system which reads shebang

How can I create a build system in Sublime Text 3 where "cmd" is replaced with a shebang if it exists?
More specifically, is there a way to alter the Python build system to use the version of Python specified in the shebang, and use a default if no shebang is present?
Sublime build systems have an option named target which specifies a WindowCommand that is to be invoked to perform the build. By default this is the internal exec command. You can create your own command that would examine the file for a shebang and use that interpreter or some default otherwise.
For example (caveat: I'm not super proficient in Python so this is probably quite ugly):
import sublime, sublime_plugin
class ShebangerCommand(sublime_plugin.WindowCommand):
def parseShebang (self, filename):
with open(filename, 'r') as handle:
shebang = handle.readline ().strip ().split (' ', 1)[0]
if shebang.startswith ("#!"):
return shebang[2:]
return None
def createExecDict(self, sourceDict):
current_file = self.window.active_view ().file_name()
args = dict (sourceDict)
interpreter = args.pop ("interpreter_default", "python")
exec_args = args.pop ("interpreter_args", ["-u"])
shebang = self.parseShebang (current_file)
args["shell_cmd"] = "{} {} \"{}\"".format (shebang or interpreter,
" ".join (exec_args),
current_file)
return args
def run(self, **kwargs):
self.window.run_command ("exec", self.createExecDict (kwargs))
You would save this in Packages/User as a python file (e.g. shebanger.py).
This creates a new command named shebanger that collects the arguments it's been given, examines the file in the currently active view of the window the build is triggered in to see if the first line is a shebang, and then synthesizes the arguments needed for the exec command and runs it.
Since the default python build system assumes it is building the current file and passing -u as an argument, that's what this command replicates as well. Note however that this code is not 100% correct because any arguments in the shebang line will be ignored, but you get the general idea.
In use, you would modify the default Python.sublime-build file to look like this:
{
// WindowCommand to execute for this build
"target": "shebanger",
// Use this when there is no shebang
"interpreter_default": "python",
// Args to pass to the interpreter
"interpreter_args": ["-u"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python",
"env": {"PYTHONIOENCODING": "utf-8"},
"variants":
[
{
"name": "Syntax Check",
"interpreter_args": ["-m py_compile"],
}
]
}
Notice that in the variant we override what the interpreter arguments are; you could also override the default interpreter there as well if desired.
If think the only way to do this using a standard .sublime-build file is to pass your file to another script which then parses the shebang and passes it on to the correct Python version.
Alternatively, you could specify build variants, but then you will have to choose the desired build variant manually.
My python.sublime-build
{
"cmd": ["py", "-u", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python",
"shell":true
}
In windows I used py launcher to detect the versions according to the shebang

Cmake add command line argument to binary

I create a binary myBinary via cmake/CMakeLists.txt.
I would like to "include" default options on my binary.
In other words, I want my binary to be called with myBinary --option myopt even when I just run ./myBinary
How can I do that?
CMake does not have built-in support for you you want to do.
One solution is to do as #Youka said - change the source code of your program.
Another solution that I have used sometimes is to autogenerate a script that executes an executable:
# Create startup script
MACRO(GEN_START_SCRIPT binName)
# Generate content
SET(fileContent
"#!/bin/bash\n"
"\n"
"# This startup script is auto generated - do not modify!\n"
"\n"
"${binName} -a 23 -b 34 -c 976\n"
"\n"
)
# Write to file
SET(fileName ${CMAKE_CURRENT_BINARY_DIR}/${binName}.sh)
FILE(WRITE ${fileName} ${fileContent})
ENDMACRO()
Then call the macro after defining your executable:
ADD_EXECUTABLE(myBinary file1.c file.2)
GEN_START_SCRIPT(myBinary)
You can of course add other stuff to the script, like environment variables etc.
If you're in control of the sources and you want different default behavior... change the sources!
This is in no way a build system issue (CMake or otherwise).

Sublime Text 3 Python 3 print while running

I can't get Python 3 to print out anything while running a script in Sublime Text. I can get it to print out after the script has finished, but I need it to print as it goes.
Here's some example code
import time
for x in range(10):
print("Test")
time.sleep(1)
Using Python 3 as the build system, I get nothing for 10 seconds, and then 10 "Tests" printed all at once.
If I run the same script using the Python 2 build system, I get 1 "Test" printed out each second, which is what I want.
Similarly if I run the script using "python3 script.py" in the terminal I get 1 "Test" printed out each second.
Can anyone tell me how to make the build system in Sublime Text 3 print out Python 3 while it runs?
You have to open your Python 3 build system configuration file, and ensure that the -u option is supplied to the command line to be executed.
For example:
# ~/.config/sublime-text-3/Packages/User/Python3.sublime-build
{
"cmd": ["/usr/bin/python3.5", "-u", "$file"],
"selector": "source.python",
"file_regex": "file \"(...*?)\", line ([0-9]+)"
}
Quoting the documentation:
-u
Force the binary layer of the stdout and stderr streams (which is
available as their buffer attribute) to be unbuffered. The text I/O
layer will still be line-buffered if writing to the console, or
block-buffered if redirected to a non-interactive file.
With this option, the ouptut of your Python script will be correctly displayed into Sublime Text while running.

Resources