1 /+ dub.json: 2 { 3 "name": "emacs-dman", 4 "targetType": "dynamicLibrary", 5 "dependencies": { 6 "d-emacs-module": { "path": ".." } 7 } 8 } 9 +/ 10 // How to test 11 // $ dub build --single ./dman.d 12 // $ emacs -batch -l dman_test.el 13 14 module dman; 15 16 import emacs_module.deimos; 17 18 import core.runtime: Runtime; 19 import std.datetime.systime : Clock; 20 import std.format : format; 21 import std.string : fromStringz; 22 23 24 private enum string dman = ` 25 o o 26 | \ 27 \ ___ / 28 |,-oo\\ 29 || || < %s 30 || || 31 || // 32 ||__// 33 '--- 34 \ \ 35 / / 36 ^ ^ 37 `; 38 39 // Wraps elisp "message" func with dman. 40 private void dman_message(T)(emacs_env* env, T arg) { 41 emacs_value func = env.intern(env, "message"); 42 emacs_value[1] args; 43 string hello = format!dman(arg); 44 args[0] = env.make_string(env, hello.ptr, hello.length); 45 env.funcall(env, func, args.length, args.ptr); 46 } 47 48 // Returns true if type of value is string. 49 bool stringp(emacs_env* env, emacs_value value) { 50 return env.eq(env, env.type_of(env, value), env.intern(env, "string")); 51 } 52 53 // Functions bellow are exported to emacs. 54 extern (C): 55 56 int plugin_is_GPL_compatible; 57 58 emacs_value dman_time( 59 emacs_env* env, ptrdiff_t nargs, emacs_value* args, void* data) { 60 dman_message(env, Clock.currTime()); 61 return env.intern(env, "t"); 62 } 63 64 emacs_value dman_say( 65 emacs_env* env, ptrdiff_t nargs, emacs_value* args, void* data) { 66 if (nargs == 1 && stringp(env, args[0])) { 67 string str; 68 char[128] buf; 69 ptrdiff_t size = buf.length; 70 // TODO(karita): Use dynamic array and handle errors. 71 env.copy_string_contents(env, args[0], buf.ptr, &size); 72 dman_message(env, fromStringz(buf)); 73 return env.intern(env, "t"); 74 } 75 dman_message(env, "Usage: (dman-say [string])"); 76 return env.intern(env, "nil"); 77 } 78 79 int emacs_module_init(emacs_runtime* ert) { 80 // Validate Emacs runtime and environment. 81 if (ert.size < emacs_runtime.sizeof) 82 return 1; 83 84 emacs_env* env = ert.get_environment(ert); 85 if (env.size < emacs_env.sizeof) 86 return 2; 87 88 // Initialize D runtime. 89 Runtime.initialize(); 90 dman_message(env, "Hello Emacs from D!!"); 91 92 // Register functions. 93 emacs_value[2] fn_sym_pair; 94 fn_sym_pair[0] = env.intern(env, "dman-time"); 95 fn_sym_pair[1] = env.make_function( 96 env, /*min_arity=*/0, /*max_arity=*/0, 97 /*function=*/&dman_time, 98 /*documentation=*/"Dman tells you current time.", 99 /*data=*/null); 100 env.funcall(env, env.intern(env, "defalias"), 101 fn_sym_pair.length, fn_sym_pair.ptr); 102 103 fn_sym_pair[0] = env.intern(env, "dman-say"); 104 fn_sym_pair[1] = env.make_function( 105 env, /*min_arity=*/1, /*max_arity=*/1, 106 /*function=*/&dman_say, 107 /*documentation=*/"Dman repeats your string.", 108 /*data=*/null); 109 env.funcall(env, env.intern(env, "defalias"), 110 fn_sym_pair.length, fn_sym_pair.ptr); 111 112 return 0; 113 }