Sublime Text 3 - Set syntax for filetype in package/plugin - lua

I am busy making a sublime text plugin/package that will ease development of lua scripts in my workplace.
We have several lua files with different extensions depending on their purpose. I want ST3 to give the proper lua syntax to these files.
I know you can set ST3 to remember syntax for a specific file extension and this is saved as a (in my case) Lua.sublime-settings file in AppData\Roaming\Sublime Text 3\Packages\User
However, if I put this file in my new plugin's folder, it's ignored.
Am I doing something wrong or is what I want not possible?

This doesn't work because syntax specific settings are only loaded from the package that defines the syntax and from the User package (so the user can customize them).
The following is a quote from the official documentation on settings:
Settings files are consulted in this order:
1. Packages/Default/Preferences.sublime-settings
2. Packages/Default/Preferences (<platform>).sublime-settings
3. Packages/User/Preferences.sublime-settings
4. <Project Settings>
5. Packages/<syntax>/<syntax>.sublime-settings
6. Packages/User/<syntax>.sublime-settings
7. <Buffer Specific Settings>
The only places where <syntax> is referenced is from the package itself and from the user package.
If I had to guess, I would say that this is because outside of the original package author that defined the syntax, all other settings would be considered user customizations, and those settings need to be in the User package (specifically in the root of it) to ensure that they're loaded last.
A simple (but undesirable) solution would be to document for the user that they have to take this step manually.
Another approach would be to add some plugin code that extends the settings when your plugin is loaded:
def plugin_loaded():
settings = sublime.load_settings("Lua.sublime-settings")
extensions = settings.get("extensions", [])
if "blarb" not in extensions:
extensions.append("blarb")
settings.set("extensions", extensions)
sublime.save_settings("Lua.sublime-settings")
If you go this route you may want to include an extra sentinel setting somewhere (in settings specific to your package or some such) that says if you did this or not instead of just forcing the setting in as the example above does.
In practice you would then check if you've set that sentinel or not instead of forcing the extension in, so that if the user decides to use some other syntax for your files you're not forcing them into the Lua syntax.
It's also possible to define your own syntax that just embeds the standard Lua syntax, which allows this to Just Work™ without having to write any code or have the user do anything:
%YAML 1.2
---
name: Blarb
scope: source.lua
file_extensions:
- blarb
contexts:
main:
- include: scope:source.lua
When you do this, the scope in the file will still be source.lua because that's what the scope in the syntax file says. and the status line will set the syntax name to Blarb. You could modify either of those to change the top level scope or displayed name, if desired.
An example would be to change the scope to source.blarb so that you could create key bindings/snippets that only apply to Lua files of your specific variant.
A potential downside/feature of this is that since the name of the syntax specific settings comes from the name of the file that provides the syntax, if the user has any Lua specific settings, they won't apply to your Blarb files by default.
Similarly anything that's specific to Lua by checking for a scope of source.lua won't work in Blarb files for same reasons, which may or may not be an issue.

Related

Consuming contents of declare_directory

I have rule A implemented with a macro that uses declare_directory to produce a set of files:
output = ctx.actions.declare_directory("selected")
Names of those files are not known in advance. The implementation returns the directory created by declare_directory with the following:
return DefaultInfo(
files = depset([output]),
)
Rule A is included in "srcs" attribute of rule B. Rule B is also implemented with a macro. Unfortunately the list of files passed to B implementation through "srcs" attribute only contains the "selected" directory created by rule A instead of files residing in that directory.
I know that Args class supports expansion of directories so I could pass names of all files in "selected" directory to a single action. What I need, however, is a separate action for every individual file for parallelism and caching. What is the best way to achieve that?
This is one of the intended use cases of directory outputs (called TreeArtifacts in the implementation), and it's implemented using ActionTemplate:
https://github.com/bazelbuild/bazel/blob/c2100ad420618bb53754508da806b5624209d9be/src/main/java/com/google/devtools/build/lib/actions/ActionTemplate.java#L24-L57
However, this is not exposed to Starlark, and has only a couple usages currently, in the Android rules AndroidBinary.java and C++ rules CcCompilationHelper.java. The Android rules and C++ rules are going to be migrated over to Starlark, so this functionality might eventually be made available in Starlark, but I'm not sure of any concrete timelines. It would probably be good to file a feature request on Github.

Project level environment variable in source path

I'd like to specify an environment variable for use in the source path (library path) at a project level.
We often have a couple of versions checked out of our SVN repository at the same time in different directories, and I'd like to specify the repository root for a project in relative terms at a project level. I could then use that path in a project's source path and I wouldn't have to include indecipherable dot dot slashes (..\) in paths.
For example, say I have checked out trunk to c:\projects\trunk. Then underneath there I have a project in <repositoryroot>\Foo\Bar\ under trunk which uses the Delphi Spring framework under <repositoryroot>\components\external\Spring4d. I end up with a whole bunch of directories in the search path with ..\..\External\Spring4D\Source at the beginning. For example ..\..\External\Spring4D\Source\Base\Collections. I would like to be able to be able to use ${Spring4D} instead, producing ${Spring4D}\Base\Collections\, which is much less wordy and it means that if you move a project or component you can change one value and it updates all paths.
I know that you can do this on a Delphi level by specifying paths in Delphi's environment variables, but I would like to achieve the same thing on a project level or repository level.
Does anyone have any ideas on how to achieve this? Are there any settings or even add-ins that would allow this sort of functionality?
You can manually edit your project file (.dproj) and add a variable there:
<PropertyGroup>
<MyVariableName>MyVariableContent</MyVariableName>
</PropertyGroup>
Later on, you can refer to the content of that variable:
<DCC_UnitSearchPath>C:\Components;$(MyVariableName)</DCC_UnitSearchPath>
You can also define a new environment variable (SystemPropertiesAdvanced.exe -> Environment variables -> Add) and then refer to that variable using the same syntax, e.g.:
<DCC_UnitSearchPath>C:\Components;$(PATH)</DCC_UnitSearchPath>
(Note that it is a very bad idea to use PATH here, it's only an example of a variable which will exist in your environment.)
You could also employ some cmd script magic to to create environment variables that point to those subdirectories and at the end call the IDE, so these environment variables are available in the IDE in the same way as global environment variables would be (see pepak's answer for that).
Pointers:
%0 is the name of the current cmd file
use tilde for file name parts

How to define and use precompiled variable in delphi directives

I want to define a precompile string variable and use it in {$include} directive in delphi, for example:
{$define FILE_NAME "lockfile"}
{$include FILE_NAME'.txt.1'}
{$include FILE_NAME'.txt.2'}
...
For security reasons (this is part of our licensing system), we don't want to use normal strings and file reading functions. Is there any capability for this purpose in Delphi?
The $INCLUDE directive does not support indirection on the file name. So, the following code:
const
someconst = 'foo';
{$INCLUDE someconst}
leads to the following error:
F1026 File not found: 'someconst.pas'
If you must use an include file, you must apply the indirection by some other means. One way could be to use the fact that the compiler will search for the included file by looking on the search path. So, if you place each client specific include file in a different directory, then you can add the client specific directory to the search path as part of your build process.
FWIW, I find it hard to believe that this will make your program more immune to hacking. I think that a more likely outcome is that your program will be just as susceptible to hacking, but that it will become much more difficult and error prone for you to build and distribute the program.
You requirement may be better satisfied by the proper use of a VCS system. You need "branches" for every customer where customer-specific files contains customer-specific data. This will avoid to litter your code with complex directive to manage each customer - file names stays the same, just their content is different in each branch. Adding a new customer just requires to create a new branch and update files there.
Then you just need get each branch and compile it for each customer to get the final executable(s) with customer specific data built in.

Is there a nice way to have different configurations for different environments?

I've created an app that requires some configuration. The way I'm doing it now is a bit hacky and tedious -- If I'm developing locally, I include the "local" configuration file (a dart file that defines a few consts) and if deploying, I include a different dart file that defines the same consts with different values.
Ideally, there would be a way to define different configurations, which could be passed to pub serve/build. It seems like such an obvious need that I feel like something may already exist and I just haven't run across it yet. Is there? Or is something in the works?
Pub build does not support defining environment variables but you can use fromEnvironment method, for example, on String:
String.fromEnvironment(String name, {String defaultValue})
Returns the string value of the environment declaration name.
Environment declarations are provided by the surrounding system
compiling or running the Dart program. Declarations map a string key
to a string value.
Or make it "fancier" with transformers. It will allow you to automatically(on pub build or pub serve) get settings from pubspec.yaml or another source and embed them in to the code. For example sass(it is transformer) package supports settings of this form:
:::yaml
transformers:
- sass:
executable: /path/to/sass # Sass executable to use
compass: true # Include compass
line-numbers: true # Include line numbers in output
style: compact # Style of generated CSS
copy-sources: true # Copy original .scss/.sass files to output directory
With it you can do pretty much anything including source code modification.

How to inform Free Pascal Compiler to set Locale ID for the compiled application

In Delphi there is an option VersionInfo->Language->Locale ID when viewing project properties.
I was wandering how to set such property for a program being compiled under Free Pascal.
Any solution is welcome: command line argument or preprocessor directive such as {$key value}; equivalent to Delphi.
If you can build your projects using *.lpi files then I would try to add the following into your project's Project.lpi file. In the following snippet is shown how to set the project's locale ID (for Windows platform) to 0405 (Czech).
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
...
<VersionInfo>
<UseVersionInfo Value="True"/>
<Language Value="0405"/>
<StringTable ProductVersion=""/>
</VersionInfo>
...
</ProjectOptions>
...
</CONFIG>
Or if you are using Lazarus IDE then you might use to Delphi very similar settings tab which you can open from Project / Project Options ... and as in Delphi go to Version Info where is the Language selection combo box available if you include the version info into the project.
Not 100% sure this will work, feel free to vote me down if this doesn't work.
Lazarus will inherit the locale settings it starts with.
You can set the locale info prior to starting Lazarus in Linux/OS X using the command line:
export LC_CTYPE="pt_BR"
export LANG="pt_BR"
export LANGUAGE="pt_BR"
./lazarus
Your compiled application should inherit these settings.
The answer is inspired by this workaround to an error has since been fixed.
I recommend you have a look at the fpc forum as well and ask the question there.
Don't forget it include details like the platform (Linux/Windows/OS X) and the exact version of FPC and Lazarus you are using as well as the actual Locale that you want.
Better answer
From: http://forum.lazarus.freepascal.org/index.php/topic,5924.0.html
Finally, I managed to find a simple and effective way to make my application localizeable. It uses just one unit and no code.
1. Add unit "defaulttranslator" to your uses list.
2. Enable "i18n" in "Project Options" and set "PO output directory" to "locale" or "languages". You can put translation files right into application folder, but that would just make a mess. Don't forget to create an appropriate folder.
3. Add components to the form. If you already have all components on your form, you'll have to move it a little bit, so it's modified.
4. Save your project.
5. Now there should be .po files in your "locale" or "languages" folder. For different languages files should be copied and renamed like so "project1.XX.po", where XX is language code (e.g. "en", "de", etc.).
6. Translate .po files with translation software, and generate .mo files. I suggest to use POEdit.
7. Run your application, and the translation to be used will be chosen by your regional locale settings. If you need to test other language - just start your application with following command line parameters - "-l XX" or "-lang XX", where XX is a language code.
This method is not very versatile, but it translates resource strings and LCL component properties.

Resources