Commit 20e6856e authored by Hisham Muhammad's avatar Hisham Muhammad
Browse files

Initial support for (still stale) plugin columns

This allows plugins to add columns, but they don't update
their values yet.
parent df003a63
Showing with 226 additions and 21 deletions
+226 -21
#include "config.h"
#include "API.h"
#include "Process.h"
#ifdef HAVE_LUA
/*{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#define check_field(_name, _type, _err) \
do { \
int typ = lua_getfield(L, 1, _name); \
if (typ != _type) { \
lua_settop(L, 0); \
lua_pushnil(L); \
lua_pushliteral(L, _err); \
return 2; \
} \
lua_pop(L, 1); \
} while(0)
#define assign_string(_var, _idx, _field) \
do { \
lua_getfield(L, _idx, _field); \
_var = xStrdup(lua_tostring(L, -1)); \
lua_pop(L, 1); \
} while(0)
}*/
int API_newColumn(lua_State* L) {
luaL_checktype(L, 1, LUA_TTABLE);
check_field("name", LUA_TSTRING, "expected 'name' field of type string");
check_field("description", LUA_TSTRING, "expected 'description' field of type string");
check_field("header", LUA_TSTRING, "expected 'header' field of type string");
check_field("format", LUA_TSTRING, "expected 'format' field of type string");
check_field("run", LUA_TFUNCTION, "expected 'run' field of type function");
lua_getfield(L, LUA_REGISTRYINDEX, "htop_columns");
lua_len(L, -1);
int len = lua_tonumber(L, -1);
lua_pop(L, 1);
ProcessFieldData* pfd = lua_newuserdata(L, sizeof(ProcessFieldData));
assign_string(pfd->name, 1, "name");
assign_string(pfd->description, 1, "description");
assign_string(pfd->title, 1, "header");
assign_string(pfd->format, 1, "format");
lua_seti(L, -2, len + 1);
lua_settop(L, 0);
lua_pushboolean(L, 1);
return 1;
}
static luaL_Reg API_functions[] = {
{ .name = "new_column", .func = API_newColumn },
{ .name = NULL, .func = NULL },
};
int API_new(lua_State* L) {
lua_settop(L, 0);
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "htop_columns");
lua_newtable(L);
luaL_setfuncs(L, API_functions, 0);
return 1;
}
#endif
/* Do not edit this file. It was automatically generated. */
#ifndef HEADER_API
#define HEADER_API
#ifdef HAVE_LUA
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#define check_field(_name, _type, _err) \
do { \
int typ = lua_getfield(L, 1, _name); \
if (typ != _type) { \
lua_settop(L, 0); \
lua_pushnil(L); \
lua_pushliteral(L, _err); \
return 2; \
} \
lua_pop(L, 1); \
} while(0)
#define assign_string(_var, _idx, _field) \
do { \
lua_getfield(L, _idx, _field); \
_var = xStrdup(lua_tostring(L, -1)); \
lua_pop(L, 1); \
} while(0)
int API_newColumn(lua_State* L);
int API_new(lua_State* L);
#endif
#endif
......@@ -18,10 +18,14 @@ in the source distribution for its full text.
/*{
#include "Panel.h"
#include "ProcessList.h"
typedef struct AvailableColumnsPanel_ {
Panel super;
Panel* columns;
#ifdef HAVE_LUA
lua_State* L;
#endif
} AvailableColumnsPanel;
}*/
......@@ -46,7 +50,22 @@ static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
case KEY_F(5):
{
int at = Panel_getSelectedIndex(this->columns);
Panel_insert(this->columns, at, (Object*) ListItem_new(Process_fields[key].name, key));
ListItem* item;
#ifdef HAVE_LUA
if (key > 1000) {
lua_State* L = this->L;
lua_getfield(L, LUA_REGISTRYINDEX, "htop_columns");
lua_geti(L, -1, key - 1000);
ProcessFieldData* pfd = (ProcessFieldData*) lua_touserdata(L, -1);
item = ListItem_new(pfd->name, key);
lua_pop(L, 2);
} else
#endif
{
item = ListItem_new(Process_fields[key].name, key);
}
Panel_insert(this->columns, at, (Object*) item);
Panel_setSelected(this->columns, at+1);
ColumnsPanel_update(this->columns);
result = HANDLED;
......@@ -70,7 +89,7 @@ PanelClass AvailableColumnsPanel_class = {
.eventHandler = AvailableColumnsPanel_eventHandler
};
AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns) {
AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns, ProcessList* pl) {
AvailableColumnsPanel* this = AllocThis(AvailableColumnsPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_new(AvailableColumnsFunctions, NULL, NULL);
......@@ -85,6 +104,24 @@ AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns) {
Panel_add(super, (Object*) ListItem_new(description, i));
}
}
#ifdef HAVE_LUA
lua_State* L = pl->L;
this->L = L;
int top = lua_gettop(L);
lua_getfield(L, LUA_REGISTRYINDEX, "htop_columns");
lua_len(L, -1);
int len = lua_tointeger(L, -1);
lua_pop(L, 1);
for (int a = 1; a <= len; a++) {
lua_geti(L, -1, a);
ProcessFieldData* pfd = (ProcessFieldData*) lua_touserdata(L, -1);
char description[256];
xSnprintf(description, sizeof(description), "%s - %s", pfd->name, pfd->description);
Panel_add(super, (Object*) ListItem_new(description, 1000 + a));
lua_pop(L, 1);
}
lua_settop(L, top);
#endif
this->columns = columns;
return this;
}
......@@ -10,15 +10,19 @@ in the source distribution for its full text.
*/
#include "Panel.h"
#include "ProcessList.h"
typedef struct AvailableColumnsPanel_ {
Panel super;
Panel* columns;
#ifdef HAVE_LUA
lua_State* L;
#endif
} AvailableColumnsPanel;
extern PanelClass AvailableColumnsPanel_class;
AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns);
AvailableColumnsPanel* AvailableColumnsPanel_new(Panel* columns, ProcessList* pl);
#endif
......@@ -66,7 +66,7 @@ static void CategoriesPanel_makeColorsPage(CategoriesPanel* this) {
static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) {
Panel* columns = (Panel*) ColumnsPanel_new(this->settings);
Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns);
Panel* availableColumns = (Panel*) AvailableColumnsPanel_new(columns, this->pl);
ScreenManager_add(this->scr, columns, 20);
ScreenManager_add(this->scr, availableColumns, -1);
}
......
......@@ -160,7 +160,7 @@ void ColumnsPanel_update(Panel* super) {
for (int i = 0; i < size; i++) {
int key = ((ListItem*) Panel_get(super, i))->key;
this->settings->fields[i] = key;
this->settings->flags |= Process_fields[key].flags;
this->settings->flags |= key < 1000 ? Process_fields[key].flags : 0;
}
this->settings->fields[size] = 0;
}
......
......@@ -37,7 +37,7 @@ BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c \
TraceScreen.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \
HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c EnvScreen.c \
InfoScreen.c XAlloc.c
InfoScreen.c XAlloc.c API.c
myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
......@@ -47,7 +47,7 @@ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h
ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h \
TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \
AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \
EnvScreen.h InfoScreen.h XAlloc.h
EnvScreen.h InfoScreen.h XAlloc.h API.h
if HTOP_LINUX
htop_CFLAGS += -rdynamic
......
......@@ -150,6 +150,7 @@ typedef struct ProcessFieldData_ {
const char* name;
const char* title;
const char* description;
const char* format;
int flags;
} ProcessFieldData;
......@@ -367,6 +368,19 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
int n = sizeof(buffer) - 1;
bool coloring = this->settings->highlightMegabytes;
#ifdef HAVE_LUA
if (field > 1000) {
lua_State* L = this->settings->L;
lua_getfield(L, LUA_REGISTRYINDEX, "htop_columns");
lua_geti(L, -1, field - 1000);
ProcessFieldData* pfd = (ProcessFieldData*) lua_touserdata(L, -1);
xSnprintf(buffer, n, pfd->format, 123);
lua_pop(L, 2);
RichString_append(str, attr, buffer);
return;
}
#endif
switch (field) {
case PERCENT_CPU: {
if (this->percent_cpu > 999.9) {
......
......@@ -129,6 +129,7 @@ typedef struct ProcessFieldData_ {
const char* name;
const char* title;
const char* description;
const char* format;
int flags;
} ProcessFieldData;
......
......@@ -10,6 +10,7 @@ in the source distribution for its full text.
#include "CRT.h"
#include "StringUtils.h"
#include "API.h"
#include <stdlib.h>
#include <string.h>
......@@ -136,26 +137,22 @@ void ProcessList_done(ProcessList* this) {
}
#ifdef HAVE_LUA
void ProcessList_initScripting(ProcessList* this) {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
this->L = L;
lua_newtable(L);
lua_pushvalue(L, 1);
lua_setglobal(L, "htop");
luaL_requiref(L, "htop", API_new, 0);
lua_pop(L, 1);
for (int i = 0; i < this->settings->nPlugins; i++) {
char* plugin = this->settings->plugins[i];
lua_getglobal(L, "require");
lua_pushliteral(L, "htop-plugins.");
lua_pushstring(L, plugin);
lua_concat(L, 2);
int ok = lua_pcall(L, 1, 1, 0);
if (ok == LUA_OK) {
lua_setfield(L, 1, plugin);
} else {
lua_pop(L, 1);
}
lua_pcall(L, 1, 1, 0);
lua_pop(L, 1);
}
}
#endif
......@@ -168,12 +165,26 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) {
RichString_prune(header);
ProcessField* fields = this->settings->fields;
for (int i = 0; fields[i]; i++) {
const char* field = Process_fields[fields[i]].title;
unsigned int key = fields[i];
const char* field;
#ifdef HAVE_LUA
if (key > 1000) {
lua_State* L = this->L;
lua_getfield(L, LUA_REGISTRYINDEX, "htop_columns");
lua_geti(L, -1, key - 1000);
ProcessFieldData* pfd = (ProcessFieldData*) lua_touserdata(L, -1);
field = pfd->title;
lua_pop(L, 2);
} else
#endif
{
field = Process_fields[key].title;
}
if (!field) field = "- ";
if (!this->settings->treeView && this->settings->sortKey == fields[i])
RichString_append(header, CRT_colors[PANEL_SELECTION_FOCUS], field);
else
RichString_append(header, CRT_colors[PANEL_HEADER_FOCUS], field);
int color = (!this->settings->treeView && this->settings->sortKey == key)
? CRT_colors[PANEL_SELECTION_FOCUS]
: CRT_colors[PANEL_HEADER_FOCUS];
RichString_append(header, color, field);
}
}
......
......@@ -90,6 +90,7 @@ ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable*
void ProcessList_done(ProcessList* this);
#ifdef HAVE_LUA
void ProcessList_initScripting(ProcessList* this);
#endif
......
......@@ -23,6 +23,12 @@ in the source distribution for its full text.
#include "Process.h"
#include <stdbool.h>
#ifdef HAVE_LUA
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#endif
typedef struct {
int len;
char** names;
......@@ -32,6 +38,10 @@ typedef struct {
typedef struct Settings_ {
char* filename;
#ifdef HAVE_LUA
lua_State* L;
#endif
MeterColumnSettings columns[2];
char** plugins;
......
......@@ -14,6 +14,12 @@ in the source distribution for its full text.
#include "Process.h"
#include <stdbool.h>
#ifdef HAVE_LUA
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#endif
typedef struct {
int len;
char** names;
......@@ -23,6 +29,10 @@ typedef struct {
typedef struct Settings_ {
char* filename;
#ifdef HAVE_LUA
lua_State* L;
#endif
MeterColumnSettings columns[2];
char** plugins;
......
......@@ -197,6 +197,7 @@ int main(int argc, char** argv) {
#ifdef HAVE_LUA
ProcessList_initScripting(pl);
settings->L = pl->L;
#endif
Header* header = Header_new(pl, settings, 2);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment