build: Add support for cargo based rust projects

In the process we needed to define if a project can be run...
Python and rust can always be run as they will build their binaries
whereas make and cmake need to be configured etc...
This commit is contained in:
Andy Williams 2017-07-04 14:10:55 +01:00
parent 3caa121b12
commit 405f93efe1
15 changed files with 355 additions and 40 deletions

View File

@ -62,7 +62,8 @@ edi_main.c \
edi_private.h
EXTRA_DIST = \
language/edi_language_provider_c.c
language/edi_language_provider_c.c \
language/edi_language_provider_rust.c
edi_LDADD = @EFL_LIBS@ $(top_builddir)/src/lib/libedi.la $(LTLIBINTL)

View File

@ -10,6 +10,8 @@
#include "edi_config.h"
#include "language/edi_language_provider.h"
#include "edi_private.h"
// TODO move out to edi_content.c or similar just like the editor type
@ -72,17 +74,17 @@ static Edi_Content_Provider _edi_content_provider_registry[] =
Edi_Content_Provider *edi_content_provider_for_mime_get(const char *mime)
{
const char *id = NULL;
Edi_Language_Provider *provider;
if (!mime)
return NULL;
if (!strcasecmp(mime, "text/plain") || !strcasecmp(mime, "application/x-shellscript"))
provider = edi_language_provider_for_mime_get(mime);
if (!!provider)
id = "code";
else if (!strcasecmp(mime, "text/plain") || !strcasecmp(mime, "application/x-shellscript"))
id = "text";
else if (!strcasecmp(mime, "text/x-chdr") || !strcasecmp(mime, "text/x-csrc")
|| !strcasecmp(mime, "text/x-modelica"))
id = "code";
else if (!strcasecmp(mime, "text/x-c++src") || !strcasecmp(mime, "text/x-c++hdr"))
id = "code";
else if (!strncasecmp(mime, "image/", 6))
id = "image";
else if (!strcasecmp(mime, "text/x-diff") || !strcasecmp(mime, "text/x-patch"))

View File

@ -600,32 +600,6 @@ edi_launcher_config_missing()
evas_object_show(popup);
}
static void
_edi_launcher_run(Edi_Project_Config_Launch *launch)
{
char *full_cmd;
int full_len;
if (!_edi_project_config->launch.path)
{
edi_launcher_config_missing();
return;
}
if (!_edi_project_config->launch.args)
{
ecore_exe_run(launch->path, NULL);
return;
}
full_len = strlen(_edi_project_config->launch.path) + strlen(_edi_project_config->launch.path);
full_cmd = malloc(sizeof(char) * (full_len + 1));
snprintf(full_cmd, full_len + 2, "%s %s", _edi_project_config->launch.path, _edi_project_config->launch.args);
ecore_exe_run(full_cmd, NULL);
free(full_cmd);
}
static void
_edi_project_credentials_missing()
@ -757,6 +731,18 @@ _edi_build_prep(Evas_Object *button)
return EINA_TRUE;
}
static void
_edi_launcher_run(Edi_Project_Config_Launch *launch)
{
if (!edi_builder_can_run(_edi_project_config->launch.path))
{
edi_launcher_config_missing();
return;
}
edi_builder_run(launch->path, launch->args);
}
static void
_tb_build_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{

View File

@ -9,6 +9,7 @@
#include "edi_private.h"
#include "edi_language_provider_c.c"
#include "edi_language_provider_rust.c"
static Edi_Language_Provider _edi_language_provider_registry[] =
{
@ -17,22 +18,35 @@ static Edi_Language_Provider _edi_language_provider_registry[] =
_edi_language_c_mime_name, _edi_language_c_snippet_get,
_edi_language_c_lookup, _edi_language_c_lookup_doc
},
{
"rust", _edi_language_rust_add, _edi_language_rust_refresh, _edi_language_rust_del,
_edi_language_rust_mime_name, _edi_language_rust_snippet_get,
NULL, NULL
},
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};
Edi_Language_Provider *edi_language_provider_get(Edi_Editor *editor)
{
Edi_Language_Provider *provider;
const char *mime = editor->mimetype;
return edi_language_provider_for_mime_get(mime);
}
Edi_Language_Provider *edi_language_provider_for_mime_get(const char *mime)
{
Edi_Language_Provider *provider;
const char *id = NULL;
if (!mime)
return NULL;
if (!strcasecmp(mime, "text/x-chdr") || !strcasecmp(mime, "text/x-csrc")
|| !strcasecmp(mime, "text/x-modelica"))
if (!strcasecmp(mime, "text/x-chdr") || !strcasecmp(mime, "text/x-csrc"))
id = "c";
if (!strcasecmp(mime, "text/rust"))
id = "rust";
if (!id)
return NULL;

View File

@ -66,6 +66,17 @@ typedef struct _Edi_Language_Provider
*/
Edi_Language_Provider *edi_language_provider_get(Edi_Editor *editor);
/**
* Look up a suggest provider based on the mime type provided.
*
* @param mime the mime type for a file you wish to get a suggestion provider for
*
* @return an Edi_Editor_Suggest_Provider if one is registered or NULL otherwise
*
* @ingroup Lookup
*/
Edi_Language_Provider *edi_language_provider_for_mime_get(const char *mime);
/**
* Query whether a suggest provider is available for the specified editor session.
*

View File

@ -0,0 +1,58 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include "edi_language_provider.h"
#include "edi_config.h"
#include "edi_private.h"
void
_edi_language_rust_add(Edi_Editor *editor EINA_UNUSED)
{
}
void
_edi_language_rust_refresh(Edi_Editor *editor EINA_UNUSED)
{
}
void
_edi_language_rust_del(Edi_Editor *editor EINA_UNUSED)
{
}
const char *
_edi_language_rust_mime_name(const char *mime)
{
if (!strcasecmp(mime, "text/rust"))
return "Rust source";
return NULL;
}
const char *
_edi_language_rust_snippet_get(const char *key)
{
if (!strcmp(key, "ret"))
return "return";
if (!strcmp(key, "if"))
return
"if ()\n" \
" {\n" \
" }";
if (!strcmp(key, "ifel"))
return
"if ()\n" \
" {\n" \
" }\n" \
"else\n" \
" {\n" \
" }";
return NULL;
}

View File

@ -25,6 +25,7 @@ libedi_la_SOURCES = \
edi_private.h \
edi_build_provider_make.c \
edi_build_provider_cmake.c \
edi_build_provider_cargo.c \
edi_build_provider_python.c \
edi_build_provider.c \
edi_builder.c \

View File

@ -9,6 +9,7 @@
extern Edi_Build_Provider _edi_build_provider_make;
extern Edi_Build_Provider _edi_build_provider_cmake;
extern Edi_Build_Provider _edi_build_provider_cargo;
extern Edi_Build_Provider _edi_build_provider_python;
EAPI Edi_Build_Provider *edi_build_provider_for_project_get()
@ -26,6 +27,8 @@ EAPI Edi_Build_Provider *edi_build_provider_for_project_path_get(const char *pat
if (_edi_build_provider_cmake.path_supported_is(path))
return &_edi_build_provider_cmake;
if (_edi_build_provider_cargo.path_supported_is(path))
return &_edi_build_provider_cargo;
if (_edi_build_provider_python.path_supported_is(path))
return &_edi_build_provider_python;
@ -38,6 +41,8 @@ EAPI Edi_Build_Provider *edi_build_provider_for_id_get(const char *id)
return &_edi_build_provider_make;
if (!strcmp("cmake", id))
return &_edi_build_provider_cmake;
if (!strcmp("cargo", id))
return &_edi_build_provider_cargo;
if (!strcmp("python", id))
return &_edi_build_provider_python;

View File

@ -16,9 +16,11 @@ typedef struct _Edi_Build_Provider
Eina_Bool (*path_supported_is)(const char *path);
Eina_Bool (*file_hidden_is)(const char *path);
Eina_Bool (*project_runnable_is)(const char *path);
void (*build)(void);
void (*test)(void);
void (*run)(const char *path, const char *args);
void (*clean)(void);
} Edi_Build_Provider;

View File

@ -0,0 +1,97 @@
#ifdef HAVE_CONFIG
# include "config.h"
#endif
#include <unistd.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include "Edi.h"
#include "edi_private.h"
static Eina_Bool
_relative_path_exists(const char *base, const char *relative)
{
char *path;
Eina_Bool ret;
path = edi_path_append(base, relative);
ret = ecore_file_exists(path);
free(path);
return ret;
}
static void
_exec_cmd(const char *cmd)
{
ecore_exe_pipe_run(cmd,
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
}
static Eina_Bool
_cargo_project_supported(const char *path)
{
return _relative_path_exists(path, "Cargo.toml");
}
static Eina_Bool
_cargo_file_hidden_is(const char *file)
{
if (!file || strlen(file) == 0)
return EINA_FALSE;
if (eina_str_has_extension(file, ".o") || !strcmp(ecore_file_file_get(file), "target"))
return EINA_TRUE;
return EINA_FALSE;
}
static Eina_Bool
_cargo_project_runnable_is(const char *file EINA_UNUSED)
{
return EINA_TRUE;
}
static void
_cargo_build(void)
{
if (chdir(edi_project_get()) == 0)
_exec_cmd("cargo build");
}
static void
_cargo_test(void)
{
if (chdir(edi_project_get()) == 0)
_exec_cmd("cargo test");
}
static void
_cargo_run(const char *path EINA_UNUSED, const char *args EINA_UNUSED)
{
if (chdir(edi_project_get()) == 0)
_exec_cmd("cargo run");
}
static void
_cargo_clean(void)
{
if (chdir(edi_project_get()) == 0)
_exec_cmd("cargo clean");
}
Edi_Build_Provider _edi_build_provider_cargo =
{
"cargo",
_cargo_project_supported,
_cargo_file_hidden_is,
_cargo_project_runnable_is,
_cargo_build,
_cargo_test,
_cargo_run,
_cargo_clean
};

View File

@ -37,6 +37,15 @@ _cmake_file_hidden_is(const char *file)
return EINA_FALSE;
}
static Eina_Bool
_cmake_project_runnable_is(const char *path)
{
if (!path || !path[0])
return EINA_FALSE;
return ecore_file_exists(path);
}
static void
_cmake_build(void)
{
@ -58,6 +67,36 @@ _cmake_test(void)
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
}
static void
_cmake_run(const char *path, const char *args)
{
char *full_cmd;
int full_len;
if (!path) return;
if (chdir(edi_project_get()) !=0)
ERR("Could not chdir");
if (!args)
{
ecore_exe_pipe_run(path, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
return;
}
full_len = strlen(path) + strlen(path);
full_cmd = malloc(sizeof(char) * (full_len + 1));
snprintf(full_cmd, full_len + 2, "%s %s", path, args);
ecore_exe_pipe_run(full_cmd, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
free(full_cmd);
}
static void
_cmake_clean(void)
{
@ -69,5 +108,5 @@ _cmake_clean(void)
}
Edi_Build_Provider _edi_build_provider_cmake =
{"cmake", _cmake_project_supported, _cmake_file_hidden_is,
_cmake_build, _cmake_test, _cmake_clean};
{"cmake", _cmake_project_supported, _cmake_file_hidden_is, _cmake_project_runnable_is,
_cmake_build, _cmake_test, _cmake_run, _cmake_clean};

View File

@ -45,6 +45,15 @@ _make_file_hidden_is(const char *file)
return EINA_FALSE;
}
static Eina_Bool
_make_project_runnable_is(const char *path)
{
if (!path || !path[0])
return EINA_FALSE;
return ecore_file_exists(path);
}
static const char *
_make_comand_compound_get(const char *prepend, const char *append)
{
@ -126,6 +135,36 @@ _make_test(void)
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
}
static void
_make_run(const char *path, const char *args)
{
char *full_cmd;
int full_len;
if (!path) return;
if (chdir(edi_project_get()) !=0)
ERR("Could not chdir");
if (!args)
{
ecore_exe_pipe_run(path, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
return;
}
full_len = strlen(path) + strlen(path);
full_cmd = malloc(sizeof(char) * (full_len + 1));
snprintf(full_cmd, full_len + 2, "%s %s", path, args);
ecore_exe_pipe_run(full_cmd, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
free(full_cmd);
}
static void
_make_clean(void)
{
@ -141,5 +180,5 @@ _make_clean(void)
}
Edi_Build_Provider _edi_build_provider_make =
{"make", _make_project_supported, _make_file_hidden_is,
_make_build, _make_test, _make_clean};
{"make", _make_project_supported, _make_file_hidden_is, _make_project_runnable_is,
_make_build, _make_test, _make_run, _make_clean};

View File

@ -50,6 +50,12 @@ _python_file_hidden_is(const char *file)
return EINA_FALSE;
}
static Eina_Bool
_python_project_runnable_is(const char *file EINA_UNUSED)
{
return EINA_TRUE;
}
static void
_python_build(void)
{
@ -64,6 +70,13 @@ _python_test(void)
_exec_cmd("./setup.py test");
}
static void
_python_run(const char *path EINA_UNUSED, const char *args EINA_UNUSED)
{
if (chdir(edi_project_get()) == 0)
_exec_cmd("./setup.py run");
}
static void
_python_clean(void)
{
@ -76,7 +89,9 @@ Edi_Build_Provider _edi_build_provider_python =
"python",
_python_project_supported,
_python_file_hidden_is,
_python_project_runnable_is,
_python_build,
_python_test,
_python_run,
_python_clean
};

View File

@ -19,6 +19,16 @@ edi_builder_can_build(void)
return !!provider;
}
EAPI Eina_Bool
edi_builder_can_run(const char *runpath)
{
Edi_Build_Provider *provider;
provider = edi_build_provider_for_project_get();
return provider && provider->project_runnable_is(runpath);
}
EAPI void
edi_builder_build(void)
{
@ -43,6 +53,18 @@ edi_builder_test(void)
provider->test();
}
EAPI void
edi_builder_run(const char *runpath, const char *args)
{
Edi_Build_Provider *provider;
provider = edi_build_provider_for_project_get();
if (!provider)
return;
provider->run(runpath, args);
}
EAPI void
edi_builder_clean(void)
{

View File

@ -32,6 +32,19 @@ extern "C" {
EAPI Eina_Bool
edi_builder_can_build(void);
/**
* Check if Edi can run the current project.
* This may depend on user configuration which is passed into the method.
*
* @return Whether or not the current project has a runnable executable.
*
* @see edi_builder_build().
*
* @ingroup Builder
*/
EAPI Eina_Bool
edi_builder_can_run(const char *runpath);
/**
* Run a build for the current project.
*
@ -52,6 +65,16 @@ edi_builder_build(void);
EAPI void
edi_builder_test(void);
/**
* Run a resulting executable for the current project.
*
* @see edi_builder_can_run().
*
* @ingroup Builder
*/
EAPI void
edi_builder_run(const char *runpath, const char *args);
/**
* Run a clean for the current project.
*