Custom Build System not displayed when set to Automatic - sublimetext3

I wrote a custom build system to compile and run a cpp file, as below:
{
"cmd": [
"clang++",
"-o",
"$file_base_name.out",
"$file",
"&&",
"./$file_base_name.out"
],
"selector": "source.cpp",
"quiet": true
}
It is not being shown in the automatic build systems, which I assume is due to the selector not being recognized. What do I need to change?

Indeed the scope selector that you're using is not correct here; the scope of C++ files is source.c++ and not source.cpp. You can use Tools > Developer > Show Scope Name from the menu (or the associated key) while you're editing a file to see the full scope at the current cursor location. For a build system the first line in the scope popup is the one you want to use.
There's another issue with your build (which you have alluded to in the comments) that the build doesn't work as expected. The reason for that is that you're using cmd to execute your build, but you're use shell constructs (the &&).
When you specify cmd in a build system, you provide a list of strings; the first item is the name of the program that you want to execute (here it's clang++), and the remaining items are arguments to be given to the program being executed.
So in this case, you're asking Sublime to execute clang++ directly, and one of the arguments that you're providing to it is &&, which it assumes is the name of a file. The intention is to try and run the program if it successfully compiles, but using && is a function of your shell (e.g. bash or the like) and not of clang.
You can try adding "shell": true to your build, which tells Sublime that it should try to execute cmd through the system shell instead; that passes everything as a whole to the shell, which does know how to handle &&.
The other alternative is to use shell_cmd instead; in that case you provide a single string that represents the command line that you would enter into the terminal. In this case when you execute the build, Sublime automatically passes the value to the shell for execution.
In your case, that might look like:
"shell_cmd": "clang++ -o \"${file_base_name}.out\" \"$file\" && \"./${file_base_name}.out\"",
Apart from the value being a single string, it's also important to note that if your filenames can potentially contain spaces, you need to wrap all filename arguments in double quotes so that the shell handles things properly.

Related

Sublime Key Binding Arguments

Sublime's key bindings accept arguments, where can I find the list of arguments I can pass for user defined key bindings?
Documentation doesn't make it clear, google is not helping, I can't find source of this dictionary, where is it all being defined? How can I review what I can use or not?
The arguments that a command takes depend on the command itself, which is true not only for default commands that ship with Sublime but also any commands added by plugins or third party packages.
The unofficial documentation has a list of commands internal to Sublime, including what they do and what arguments they take which can be of help here. For example, given this text:
new_window
Opens a new window.
The command new_window takes no arguments. On the other hand:
expand_selection
Extends the selection up to predefined limits.
to [Enum]: Values: bol, hardbol, eol, hardeol, bof, eof, brackets, line, tag, scope, indentation.
The expand_selection command takes an argument named to, and also has a list of predefined values that it can take, e.g. "to": "bol" to expand the selection to the beginning of the line.
To my knowledge there's no official list of internal commands with the exception that they're used in the default key bindings (which appear in the left hand pane of the key bindings window when you open it).
Third party packages that define commands sometimes outline them in their README file, but many also choose to go the same route as Sublime and just document them in the key bindings files.
It's also possible for commands to appear in other places (e.g. in menus and in the command palette), which is another place to look. You can use the internal View Package File command to view sublime-command and sublime-menu files to see what they're doing as well, if you're curious.
Lastly, if you open the Sublime console and enter the command sublime.log_commands(True), Sublime will log commands as they execute, telling you what they are and what arguments they took. Note however that there is currently an issue in more recent builds where commands from the command palette are not always logged.

Change root-path for bash auto-completition (TAB) feature

Can I force BASH to see certain folder (let's call it main_folder) as the root of my file-system? I need BASH to behave this way at least during auto-completion of parameter names and command names, while inside the folder.
Let's say that I have directory tree that looks like this:
/z/y/main_folder/a.txt
/z/y/main_folder/bin/b.txt
/z/y/main_folder/bin/c.txt
/z/y/main_folder/bin/d.sh
Now that I call this custom version of bash, I could simply type:
/> /bi(TAB)/(TAB) /a(TAB)
What would expand to:
/> /bin/d.sh /a.txt
Where d.sh is command to be run and a.txt is it's first parameter. If I was CDed into /bin/ I could do:
/bin/> ./(TAB) (TAB)(TAB)
What would expand the command d.sh, and would give three options for the first parameter (namely: b.txt, c.txt, d.sh).
Few brief additional points:
I do not care if the original root of the file-system is inaccessible or is accessible via hard/soft link.
I do not care if I am able to run any commands that are out of scope for main_folder (I will change the $PATH variable anyway) or any shell builtins.
I do not care what the $PS#, $PWD, etc. variables actually hold.
I do not want to make my own version of BASH (changing source-code). My application should (probably) be started via some script (sh) or program (C/C++/C#) that setups the environment and either continues in interactive mode or runs interactive shell on one of it's last lines.
I want to run this as an unprivileged user. I do not want to allow the user to chroot.
I am not concerned with security, and I am not intending to jail anyone. I simply need BASH to auto-complete.
I would not mind to 'trap' BASH during directory lookups.
I have a feeling that set, compgen, complete and compopt builtins are what I need to utilize, but I do not know how. It does not seem that the examples I have found about these commands show all the features, and man pages are quite chaotic.
Thanks, Kupto :)

Bash script ignores arguments when in /bin

I have this bash script that I can pass up to three arguments to. It works like a charm when I call it from the directory ./script -h but when I copy the same file to /bin and call it from anywhere with script -h, it seems to ignore the arguments passed.
Why? or maybe more importantly:
What can I do do change that?
script is a very useful standard utility program which take a copy of your current session (look for a file called typescript). It creates another shell interface, so you probably didn't notice it was running.
When you write a new program, use a naming convention, like script.sh.
Edit:
If you don't like using a file suffix (because it looks too much like Windows) then fine, but use some other naming convention which will ensure your script names do not clash with existing commands. test is another favorite, for example. You can use type to check a command, but that only checks your current environment, you might still have a name collision when running from a different username, for example.

Check from within bash script that autocompletion is initialized

I'm looking for a method to check from within my shell script that script specific completion have been initialized by user using complete -F ...
I want this check to print out an advice on how to initialize the completion like:
Warning: Auto completion is not initialized. Please run : source ....; complete -F ...
The problem is that the script,being run in a sub-shell has no information about "complete" environment of the parent shell where user is working.
So complete -p| grep my-script-name never return any result.
User is expected to run "source" and "complete" commands or add them into his .bashrc manually, because we're working on a server where we have no access to the bash completion system directory.
Alternatively if you know a method of initializing(and not only checking) the auto-complete from within the script, I would happily accept it.
The only way your script can have access to such information for the parent shell is if it is included instead of executed as a sub-shell. Rather than instructing your users they can include some configuration, you can design your script so it works whether it is run or included.
Then you can simply inform your users that if they want completion enabled they need to include your script rather than run it as an executable script (with instuctions to use source or . as you wish).
However, in this case, I would be inclined to either add this information in documentation or add it into a banner which is always displayed (but can be disabled with an option switch like -q), rather than support two modes of running the script (since the gain is so small).
Either you want every user to use bash completion (which I don't think is good, for example I prefer to have it turned off), or let users decide themselves, but having them this message printed out on each TABTAB is a threat, don't you think?
I'd put into /etc/bash.bashrc what you think every user should run.

change shell directory from a script?

i want to make a script (to) that makes it easier for me to enter folders.
so eg. if i type "to apache" i want it to change the current directory to /etc/apache2.
however, when i use the "cd" command inside the script, it seems like it changes the path WITHIN the script, so the path in the shell has not changed.
how could i make this work?
Use an alias or function, or source the script instead of executing it.
BASH FAQ entry #60.
use a function
to_apache(){
cd /etc/apache
}
put in a file eg mylibrary.sh and whenever you want to use it, source the file. eg
#!/bin/bash
source /path/mylibrary.sh
to_apache
As Ignacio said, make it into a function (or perhaps an alias).
The way I tend to do it is have a shell script that creates the function - and the script and the function have the same name. Then once at some point in time, I will source the script ('. funcname') and thereafter I can simply use the function.
I tend to prefer functions to aliases; it is easier to manage arguments etc.
Also, for the specific case of changing directories, I use CDPATH. The trick with using CDPATH is to have the empty entry at the start:
export CDPATH=:/work4/jleffler:/u/jleffler:/work4/jleffler/src:\
/work4/jleffler/src/perl:/work4/jleffler/src/sqltools:/work4/jleffler/lib:\
/work4/jleffler/doc:/u/jleffler/mail:/work4/jleffler/work:/work4/jleffler/ids
On this machine, my main home directory is /work4/jleffler. I can get to most of the relevant sub-directories in one go with 'cd whatever'.
If you don't put the empty entry (or an explicit '.') first, then you can't 'cd' into a sub-directory of the current directory, which is disconcerting at least.
Ignacio Vazquez-Abrams gave a link to what probably answers the question, although I didn't really follow it. The short answer is to use either "source" or a single dot before the command, eg:
. to apache
But, I found there are down problems to this if you have a more complicated script. It seems that the original script filename variable ($0) is lost. I see "-bash" instead, so your script can't echo error text that that would include the full filename.
Also, you can't use the "exit" command, or your shell will exit (especially disconcerting from ssh).
Also, the "basename" function gives an error if you use that.
So, it seems to me that a function might be the only way to get around some of these problems, like if you are passing parameters.

Resources