comparison src/channel.c @ 8159:d0958e22d9ff v7.4.1373

commit https://github.com/vim/vim/commit/ece61b06ef4726515177c9b293e1c20d2122a73f Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 20 21:39:05 2016 +0100 patch 7.4.1373 Problem: Calling a Vim function over a channel requires turning the arguments into a string. Solution: Add the "call" command. (Damien) Also merge "expr" and "eval" into one.
author Christian Brabandt <cb@256bit.org>
date Sat, 20 Feb 2016 21:45:04 +0100
parents 74b44d06d3c7
children 973686665238
comparison
equal deleted inserted replaced
8158:75ab0b5bb16e 8159:d0958e22d9ff
1078 item = item->jq_next; 1078 item = item->jq_next;
1079 } 1079 }
1080 return FAIL; 1080 return FAIL;
1081 } 1081 }
1082 1082
1083 #define CH_JSON_MAX_ARGS 4
1084
1083 /* 1085 /*
1084 * Execute a command received over "channel"/"part" 1086 * Execute a command received over "channel"/"part"
1085 * "cmd" is the command string, "arg2" the second argument. 1087 * "argv[0]" is the command string.
1086 * "arg3" is the third argument, NULL if missing. 1088 * "argv[1]" etc. have further arguments, type is VAR_UNKNOWN if missing.
1087 */ 1089 */
1088 static void 1090 static void
1089 channel_exe_cmd( 1091 channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
1090 channel_T *channel, 1092 {
1091 int part, 1093 char_u *cmd = argv[0].vval.v_string;
1092 char_u *cmd, 1094 char_u *arg;
1093 typval_T *arg2, 1095 int options = channel->ch_part[part].ch_mode == MODE_JS ? JSON_JS : 0;
1094 typval_T *arg3) 1096
1095 { 1097 if (argv[1].v_type != VAR_STRING)
1096 char_u *arg; 1098 {
1097 1099 ch_error(channel, "received command with non-string argument");
1098 if (arg2->v_type != VAR_STRING)
1099 {
1100 if (p_verbose > 2) 1100 if (p_verbose > 2)
1101 EMSG("E903: received ex command with non-string argument"); 1101 EMSG("E903: received command with non-string argument");
1102 return; 1102 return;
1103 } 1103 }
1104 arg = arg2->vval.v_string; 1104 arg = argv[1].vval.v_string;
1105 if (arg == NULL) 1105 if (arg == NULL)
1106 arg = (char_u *)""; 1106 arg = (char_u *)"";
1107 1107
1108 if (STRCMP(cmd, "ex") == 0) 1108 if (STRCMP(cmd, "ex") == 0)
1109 { 1109 {
1133 gui_update_cursor(FALSE, FALSE); 1133 gui_update_cursor(FALSE, FALSE);
1134 gui_mch_flush(); 1134 gui_mch_flush();
1135 } 1135 }
1136 #endif 1136 #endif
1137 } 1137 }
1138 else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "eval") == 0) 1138 else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "call") == 0)
1139 { 1139 {
1140 int is_eval = cmd[1] == 'v'; 1140 int is_call = cmd[0] == 'c';
1141 1141 int id_idx = is_call ? 3 : 2;
1142 if (is_eval && (arg3 == NULL || arg3->v_type != VAR_NUMBER)) 1142
1143 { 1143 if (argv[id_idx].v_type != VAR_UNKNOWN
1144 && argv[id_idx].v_type != VAR_NUMBER)
1145 {
1146 ch_error(channel, "last argument for expr/call must be a number");
1144 if (p_verbose > 2) 1147 if (p_verbose > 2)
1145 EMSG("E904: third argument for eval must be a number"); 1148 EMSG("E904: last argument for expr/call must be a number");
1149 }
1150 else if (is_call && argv[2].v_type != VAR_LIST)
1151 {
1152 ch_error(channel, "third argument for call must be a list");
1153 if (p_verbose > 2)
1154 EMSG("E904: third argument for call must be a list");
1146 } 1155 }
1147 else 1156 else
1148 { 1157 {
1149 typval_T *tv; 1158 typval_T *tv;
1159 typval_T res_tv;
1150 typval_T err_tv; 1160 typval_T err_tv;
1151 char_u *json = NULL; 1161 char_u *json = NULL;
1152 int options = channel->ch_part[part].ch_mode == MODE_JS
1153 ? JSON_JS : 0;
1154 1162
1155 /* Don't pollute the display with errors. */ 1163 /* Don't pollute the display with errors. */
1156 ++emsg_skip; 1164 ++emsg_skip;
1157 tv = eval_expr(arg, NULL); 1165 if (!is_call)
1158 if (is_eval) 1166 tv = eval_expr(arg, NULL);
1167 else if (func_call(arg, &argv[2], NULL, &res_tv) == OK)
1168 tv = &res_tv;
1169 else
1170 tv = NULL;
1171
1172 if (argv[id_idx].v_type == VAR_NUMBER)
1159 { 1173 {
1174 int id = argv[id_idx].vval.v_number;
1175
1160 if (tv != NULL) 1176 if (tv != NULL)
1161 json = json_encode_nr_expr(arg3->vval.v_number, tv, 1177 json = json_encode_nr_expr(id, tv, options);
1162 options);
1163 if (tv == NULL || (json != NULL && *json == NUL)) 1178 if (tv == NULL || (json != NULL && *json == NUL))
1164 { 1179 {
1165 /* If evaluation failed or the result can't be encoded 1180 /* If evaluation failed or the result can't be encoded
1166 * then return the string "ERROR". */ 1181 * then return the string "ERROR". */
1167 vim_free(json); 1182 vim_free(json);
1168 free_tv(tv); 1183 free_tv(tv);
1169 err_tv.v_type = VAR_STRING; 1184 err_tv.v_type = VAR_STRING;
1170 err_tv.vval.v_string = (char_u *)"ERROR"; 1185 err_tv.vval.v_string = (char_u *)"ERROR";
1171 tv = &err_tv; 1186 tv = &err_tv;
1172 json = json_encode_nr_expr(arg3->vval.v_number, tv, 1187 json = json_encode_nr_expr(id, tv, options);
1173 options);
1174 } 1188 }
1175 if (json != NULL) 1189 if (json != NULL)
1176 { 1190 {
1177 channel_send(channel, part, json, "eval"); 1191 channel_send(channel,
1192 part == PART_SOCK ? PART_SOCK : PART_IN,
1193 json, (char *)cmd);
1178 vim_free(json); 1194 vim_free(json);
1179 } 1195 }
1180 } 1196 }
1181 --emsg_skip; 1197 --emsg_skip;
1182 if (tv != &err_tv) 1198 if (tv == &res_tv)
1199 clear_tv(tv);
1200 else if (tv != &err_tv)
1183 free_tv(tv); 1201 free_tv(tv);
1184 } 1202 }
1185 } 1203 }
1186 else if (p_verbose > 2) 1204 else if (p_verbose > 2)
1205 {
1206 ch_errors(channel, "Receved unknown command: %s", (char *)cmd);
1187 EMSG2("E905: received unknown command: %s", cmd); 1207 EMSG2("E905: received unknown command: %s", cmd);
1208 }
1188 } 1209 }
1189 1210
1190 /* 1211 /*
1191 * Invoke a callback for "channel"/"part" if needed. 1212 * Invoke a callback for "channel"/"part" if needed.
1192 * Return TRUE when a message was handled, there might be another one. 1213 * Return TRUE when a message was handled, there might be another one.
1194 static int 1215 static int
1195 may_invoke_callback(channel_T *channel, int part) 1216 may_invoke_callback(channel_T *channel, int part)
1196 { 1217 {
1197 char_u *msg = NULL; 1218 char_u *msg = NULL;
1198 typval_T *listtv = NULL; 1219 typval_T *listtv = NULL;
1199 list_T *list; 1220 typval_T argv[CH_JSON_MAX_ARGS];
1200 typval_T *typetv;
1201 typval_T argv[3];
1202 int seq_nr = -1; 1221 int seq_nr = -1;
1203 ch_mode_T ch_mode = channel->ch_part[part].ch_mode; 1222 ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
1204 char_u *callback = NULL; 1223 char_u *callback = NULL;
1205 1224
1206 if (channel->ch_close_cb != NULL) 1225 if (channel->ch_close_cb != NULL)
1212 else 1231 else
1213 callback = channel->ch_callback; 1232 callback = channel->ch_callback;
1214 1233
1215 if (ch_mode == MODE_JSON || ch_mode == MODE_JS) 1234 if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
1216 { 1235 {
1236 listitem_T *item;
1237 int argc = 0;
1238
1217 /* Get any json message in the queue. */ 1239 /* Get any json message in the queue. */
1218 if (channel_get_json(channel, part, -1, &listtv) == FAIL) 1240 if (channel_get_json(channel, part, -1, &listtv) == FAIL)
1219 { 1241 {
1220 /* Parse readahead, return when there is still no message. */ 1242 /* Parse readahead, return when there is still no message. */
1221 channel_parse_json(channel, part); 1243 channel_parse_json(channel, part);
1222 if (channel_get_json(channel, part, -1, &listtv) == FAIL) 1244 if (channel_get_json(channel, part, -1, &listtv) == FAIL)
1223 return FALSE; 1245 return FALSE;
1224 } 1246 }
1225 1247
1226 list = listtv->vval.v_list; 1248 for (item = listtv->vval.v_list->lv_first;
1227 argv[1] = list->lv_first->li_next->li_tv; 1249 item != NULL && argc < CH_JSON_MAX_ARGS;
1228 typetv = &list->lv_first->li_tv; 1250 item = item->li_next)
1229 if (typetv->v_type == VAR_STRING) 1251 argv[argc++] = item->li_tv;
1230 { 1252 while (argc < CH_JSON_MAX_ARGS)
1231 typval_T *arg3 = NULL; 1253 argv[argc++].v_type = VAR_UNKNOWN;
1232 char_u *cmd = typetv->vval.v_string; 1254
1233 1255 if (argv[0].v_type == VAR_STRING)
1234 /* ["cmd", arg] or ["cmd", arg, arg] */ 1256 {
1235 if (list->lv_len == 3) 1257 char_u *cmd = argv[0].vval.v_string;
1236 arg3 = &list->lv_last->li_tv; 1258
1259 /* ["cmd", arg] or ["cmd", arg, arg] or ["cmd", arg, arg, arg] */
1237 ch_logs(channel, "Executing %s command", (char *)cmd); 1260 ch_logs(channel, "Executing %s command", (char *)cmd);
1238 channel_exe_cmd(channel, part, cmd, &argv[1], arg3); 1261 channel_exe_cmd(channel, part, argv);
1239 free_tv(listtv); 1262 free_tv(listtv);
1240 return TRUE; 1263 return TRUE;
1241 } 1264 }
1242 1265
1243 if (typetv->v_type != VAR_NUMBER) 1266 if (argv[0].v_type != VAR_NUMBER)
1244 { 1267 {
1245 ch_error(channel, 1268 ch_error(channel,
1246 "Dropping message with invalid sequence number type"); 1269 "Dropping message with invalid sequence number type");
1247 free_tv(listtv); 1270 free_tv(listtv);
1248 return FALSE; 1271 return FALSE;
1249 } 1272 }
1250 seq_nr = typetv->vval.v_number; 1273 seq_nr = argv[0].vval.v_number;
1251 } 1274 }
1252 else if (channel_peek(channel, part) == NULL) 1275 else if (channel_peek(channel, part) == NULL)
1253 { 1276 {
1254 /* nothing to read on RAW or NL channel */ 1277 /* nothing to read on RAW or NL channel */
1255 return FALSE; 1278 return FALSE;