Sublime Forum

Project-relative path to a file in a build/snippet variable

#1

Cross-posted from StackOverflow]

I am trying to define a build system command which specifies some target derived directly from the current file open in the editor, but using a project-relative path rather than the absolute path to the file.

How is it possible to use snippet variables in a build rule to describe the relative path to the current $file from the project root?

[size=150]Example[/size]
For example, assume a simple Makefile which defines rules for *.o in terms of *.c, and a project containing such source files spread over multiple subdirectories.

It is useful to be able to define a build command which runs make with a target derived from the current file, like:

make ${file/\\.c/\\.o/}

but Makefile targets nearly always use relative paths, while $file and other such variables have absolute paths (or no path prefix at all). Because of this, the above command will not match any known rules in the Makefile, while $file_name, alone, does not include any local directories between the Makefile and the target (${project_path}/abc/def.c just becomes def.c not the complete local path abc/def.c which make would understand).

How is it possible to expand a variable to get the project-relative path of the current $file?

[size=150]A failed attempt[/size]
It does not seem possible to nest variables inside the regex terms of another variable expansion. For example, this does not work:

# delete the project path prefix of $file by replacing it with "":
${file/${project_path}//}

let alone this:

# delete the project path prefix of $file by replacing it with "",
# then replace .c with .o to get the target:
${${file/${project_path}//}/.c/.o/}

Aside
I realize in the simple case of compiling trivial C files to corresponding objects, I could rewrite the compile rule directly as a build system command operating directly on the absolute file paths. This is what most of the built-in build systems do. But assume that my build rules are complex and involve multiple steps, but that I still have a bunch of related targets corresponding to each input file I might be editing. (The actual case I’m working on is not, in fact, C compilation to object files.)

0 Likes

#2

Hi,

I’d like to bump this post.

ATM I am writing some plugins for c++, especially file templates. And to automatically fill in the namespaces as the files are placed in the directory structure I’d like to have project-relative paths.

Any other solution is also appreciated.

[code]
<![CDATA[
#ifndef ${TM_FILEPATH/(([A-Za-z]+)/src/)|./\U(?1:$2_)\E/g}${TM_FILENAME/(([A-Z])([A-Z][a-z]))|(([a-z])([A-Z]))|([a-z])|(.)/\U(?1:$2_$3)(?4:$5_$6)$7(?8:)\E/g}
#define ${TM_FILEPATH/(([A-Za-z]+)/src/)|./\U(?1:$2
)\E/g}${TM_FILENAME/(([A-Z])([A-Z][a-z]))|(([a-z])([A-Z]))|([a-z])|(.)/\U(?1:$2_$3)(?4:$5_$6)$7(?8:_)\E/g}

${1:#include “${2:${3:BaseClass}.hpp}”

}namespace ${4} {
class ${TM_FILENAME/(([A-Za-z])([A-Za-z0-9])).[A-Za-z0-9]/\U$2\E$3/g} ${6:: public ${3}} {
private:
${0:/* Variables */}

public:
	explicit ${TM_FILENAME/(([A-Za-z])([A-Za-z0-9]*))\.[A-Za-z0-9]*/\U$2\E$3/g}();
	~${TM_FILENAME/(([A-Za-z])([A-Za-z0-9]*))\.[A-Za-z0-9]*/\U$2\E$3/g}();
};

}

#endif /* ${TM_FILEPATH/(([A-Za-z]+)/src/)|./\U(?1:$2_)\E/g}${TM_FILENAME/(([A-Z])([A-Z][a-z]))|(([a-z])([A-Z]))|([a-z])|(.)/\U(?1:$2_$3)(?4:$5_$6)$7(?8:_)\E/g} */
]]>

class (Header)

source.c++

[/code]

Thanks for reading.

0 Likes