Skip to content

Instantly share code, notes, and snippets.

@michaelbartnett
Last active July 27, 2017 11:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaelbartnett/beb5509b3cb5a48e33054e9d68421d8d to your computer and use it in GitHub Desktop.
Save michaelbartnett/beb5509b3cb5a48e33054e9d68421d8d to your computer and use it in GitHub Desktop.
clang-shebang. frankensteined shell script and c++ code plus projectile and emacs equals ugly-cute build system

Clang-Shebang

Terminal Usage

$ cp clangshebang.cpp myprogram.cpp
$ chmod +x myprogram.cpp
$ ./myprogram.cpp
hello shell

Emacs usage

In Emacs init.el:

(global-set-key (kbd "<f5>") #'my/try-build-run-project)
(global-set-key (kbd "<f7>") #'my/try-build-project)

In emacs session, hit f5. It will run myprogram.cpp.

Projectile Usage

In terminal:

$ ./myprogram.cpp --gen-emacs-dirlocals

In emacs session, hit f5. It will do the right thing.

If you just want to build, hit f7.

I haven't added projectile-projectile-test-cmd yet because I am lazy.

#if 0
if [ "$1" == "--gen-emacs-dirlocals" ]; then
if [ -f ".dir-locals.el" ]; then
echo ".dir-locals.el already exists, you'll have to edit them yourself, sorry"
exit 1
else
touch .projectile
touch .dir-locals.el
echo "((nil . ((projectile-project-run-cmd . \"$0 --just-run\")" >> .dir-locals.el
echo " (projectile-project-compilation-cmd . \"$0 --just-compile\")" >> .dir-locals.el
echo " )))" >> .dir-locals.el
echo "Generated .dir-locals.el"
ehco 'You may need to run(hack-dir-local-variables-non-file-buffer) inside Emacs'
exit 0
fi
fi
compiler_command=$CC
if [ "$compiler_command" == "" ]; then
compiler_command="clang++"
fi
outfile=${0%.*}
default_compiler_flags=" \
-g -std=c++1y -Weverything -Wpedantic -Werror -Wno-c++98-compat \
-Wno-missing-prototypes -Wno-padded -Wno-double-promotion -Wno-documentation -Wno-documentation-unknown-command \
-Wno-gnu-anonymous-struct -Wno-nested-anon-types -Wno-c++98-compat-pedantic -Wno-newline-eof -Wno-old-style-cast \
-Wno-sign-conversion -Wno-comma -Wno-implicit-fallthrough -Wno-reserved-id-macro -Wno-cast-align -Wno-shadow \
-Wno-shorten-64-to-32 -Wno-conversion -Wno-conditional-uninitialized"
#library_flags="$(pkg-config --libs --cflags glfw3) -framework OpenGL -I./nanovg -I./nanovg_data"
#additional_sources="nanovg/*.c nanovg_data/demo.c nanovg_data/perf.c"
test -f $outfile
compile_result=$?
if [ "$1" != "--just-run" ]; then
echo compiling...
$compiler_command -x c++ $CFLAGS $default_compiler_flags $0 $additional_sources $library_flags -o "$outfile"
compile_result=$?
echo done compiling
fi
if [ "$compile_result" == "0" ]; then
if [ "$1" != "--just-compile" ]; then
$outfile
exit $?
fi
else
if [ "$1" == "--just-run" ]; then
echo $outfile not found
fi
fi
exit $compile_result
#endif
#include <cstdio>
int main()
{
std::printf("hello shell\n");
return 0;
}
;; (require 'projectile)
(defun my/prompt-save-buffer ()
"Kinda like `save-some-buffers' except it only prompts for the current buffer."
(when (buffer-modified-p)
(map-y-or-n-p "Save %s ?" (lambda (_) (save-buffer)) (list (buffer-name)))))
(defun my/projectile-compile-and-run (arg &optional dir)
"Build and run projectile project. Concatenates
`projectile-compilation-command' and `projectile-run-command'
with a && like so:
\"($projectile-compilation-command) && ($projectile-run-command)\"
It's otherwise equivalent to the execution of those two
functions. You have to confirm each command string."
(interactive "P")
(when (projectile-project-p)
(let* ((project-root (projectile-project-root))
(default-directory (or dir (projectile-compilation-dir)))
(default-compile-cmd (projectile-compilation-command default-directory))
(compile-cmd (projectile-maybe-read-command arg default-compile-cmd "Compile command: "))
(default-run-cmd (projectile-run-command project-root))
(run-cmd (projectile-maybe-read-command arg default-run-cmd "Run command: "))
(final-cmd (concat "("compile-cmd ") && (" run-cmd ")")))
(puthash default-directory compile-cmd projectile-compilation-cmd-map)
(puthash project-root run-cmd projectile-run-cmd-map)
(save-some-buffers (not compilation-ask-about-save)
(lambda ()
(projectile-project-buffer-p (current-buffer)
project-root)))
;; Pass a lambda to projectile-run-compilation so that we can add
;; the `t' parameter to `compilation-start', which ruyns the
;; compilation buffer under `comint-mode' mode, so it can read
;; keyboard input.
(projectile-run-compilation (lambda () (compilation-start final-cmd t))))))
(defun my/try-build-run-project ()
"A sort of catch-all for build & run systems. Only handles
projectile via `my/projectile-compile-and-run' right now, but could add more."
(interactive)
(hack-dir-local-variables-non-file-buffer)
(let ((file-name (buffer-file-name)))
(cond
((and (projectile-project-p) (not (equal projectile-project-run-cmd 'project-self-run)))
(let ((project-root (projectile-project-root)))
(if (and (projectile-compilation-command project-root)
(projectile-run-command project-root))
(call-interactively #'my/projectile-compile-and-run)
(message "No compile/run commands defined for this project."))))
((and file-name (file-executable-p file-name))
(my/prompt-save-buffer)
(compilation-start file-name t))
(nil (message "Not in a project and current buffer not executable")))))
(defun my/try-build-project ()
"Like `my/try-build-run-project', but only for building."
(interactive)
(hack-dir-local-variables-non-file-buffer)
(if (not (projectile-project-p))
(message "Not in a project")
(let ((project-root (projectile-project-root)))
(if (projectile-compilation-command project-root)
(call-interactively #'projectile-compile-project)
(message "No compile command defined for this project.")))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment