diff --git a/tools/virsh-completer-domain.c b/tools/virsh-completer-domain.c
index 9cc27b84cb..d4c877cd04 100644
--- a/tools/virsh-completer-domain.c
+++ b/tools/virsh-completer-domain.c
@@ -476,17 +476,10 @@ virshDomainInterfaceAddrSourceCompleter(vshControl *ctl G_GNUC_UNUSED,
                                         const vshCmd *cmd G_GNUC_UNUSED,
                                         unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST + 1);
-
-    for (i = 0; i < VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST; i++)
-        ret[i] = g_strdup(virshDomainInterfaceAddressesSourceTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST,
+                             virshDomainInterfaceAddressesSourceTypeToString);
 }
 
 
@@ -495,17 +488,10 @@ virshDomainInterfaceSourceModeCompleter(vshControl *ctl G_GNUC_UNUSED,
                                         const vshCmd *cmd G_GNUC_UNUSED,
                                         unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIRSH_DOMAIN_INTERFACE_SOURCE_MODE_LAST + 1);
-
-    for (i = 0; i < VIRSH_DOMAIN_INTERFACE_SOURCE_MODE_LAST; i++)
-        ret[i] = g_strdup(virshDomainInterfaceSourceModeTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIRSH_DOMAIN_INTERFACE_SOURCE_MODE_LAST,
+                             virshDomainInterfaceSourceModeTypeToString);
 }
 
 
@@ -514,17 +500,10 @@ virshDomainHostnameSourceCompleter(vshControl *ctl G_GNUC_UNUSED,
                                    const vshCmd *cmd G_GNUC_UNUSED,
                                    unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIRSH_DOMAIN_HOSTNAME_SOURCE_LAST + 1);
-
-    for (i = 0; i < VIRSH_DOMAIN_HOSTNAME_SOURCE_LAST; i++)
-        ret[i] = g_strdup(virshDomainHostnameSourceTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIRSH_DOMAIN_HOSTNAME_SOURCE_LAST,
+                             virshDomainHostnameSourceTypeToString);
 }
 
 
@@ -533,20 +512,17 @@ virshDomainPerfEnableCompleter(vshControl *ctl,
                               const vshCmd *cmd,
                               unsigned int flags)
 {
-    size_t i = 0;
     g_auto(GStrv) events = NULL;
     const char *event = NULL;
 
     virCheckFlags(0, NULL);
 
-    events = g_new0(char *, VIR_PERF_EVENT_LAST + 1);
-
-    for (i = 0; i < VIR_PERF_EVENT_LAST; i++)
-        events[i] = g_strdup(virPerfEventTypeToString(i));
-
     if (vshCommandOptStringQuiet(ctl, cmd, "enable", &event) < 0)
         return NULL;
 
+    events = virshEnumComplete(VIR_PERF_EVENT_LAST,
+                               virPerfEventTypeToString);
+
     return virshCommaStringListComplete(event, (const char **)events);
 }
 
@@ -556,20 +532,17 @@ virshDomainPerfDisableCompleter(vshControl *ctl,
                                 const vshCmd *cmd,
                                 unsigned int flags)
 {
-    size_t i = 0;
     g_auto(GStrv) events = NULL;
     const char *event = NULL;
 
     virCheckFlags(0, NULL);
 
-    events = g_new0(char *, VIR_PERF_EVENT_LAST + 1);
-
-    for (i = 0; i < VIR_PERF_EVENT_LAST; i++)
-        events[i] = g_strdup(virPerfEventTypeToString(i));
-
     if (vshCommandOptStringQuiet(ctl, cmd, "disable", &event) < 0)
         return NULL;
 
+    events = virshEnumComplete(VIR_PERF_EVENT_LAST,
+                               virPerfEventTypeToString);
+
     return virshCommaStringListComplete(event, (const char **)events);
 }
 
@@ -871,19 +844,10 @@ virshDomainSignalCompleter(vshControl *ctl G_GNUC_UNUSED,
                            const vshCmd *cmd G_GNUC_UNUSED,
                            unsigned int flags)
 {
-    g_auto(GStrv) tmp = NULL;
-    size_t i = 0;
-
     virCheckFlags(0, NULL);
 
-    tmp = g_new0(char *, VIR_DOMAIN_PROCESS_SIGNAL_LAST + 1);
-
-    for (i = 0; i < VIR_DOMAIN_PROCESS_SIGNAL_LAST; i++) {
-        const char *name = virshDomainProcessSignalTypeToString(i);
-        tmp[i] = g_strdup(name);
-    }
-
-    return g_steal_pointer(&tmp);
+    return virshEnumComplete(VIR_DOMAIN_PROCESS_SIGNAL_LAST,
+                             virshDomainProcessSignalTypeToString);
 }
 
 
@@ -892,19 +856,10 @@ virshDomainLifecycleCompleter(vshControl *ctl G_GNUC_UNUSED,
                               const vshCmd *cmd G_GNUC_UNUSED,
                               unsigned int flags)
 {
-    g_auto(GStrv) tmp = NULL;
-    size_t i = 0;
-
     virCheckFlags(0, NULL);
 
-    tmp = g_new0(char *, VIR_DOMAIN_LIFECYCLE_LAST + 1);
-
-    for (i = 0; i < VIR_DOMAIN_LIFECYCLE_LAST; i++) {
-        const char *name = virshDomainLifecycleTypeToString(i);
-        tmp[i] = g_strdup(name);
-    }
-
-    return g_steal_pointer(&tmp);
+    return virshEnumComplete(VIR_DOMAIN_LIFECYCLE_LAST,
+                             virshDomainLifecycleTypeToString);
 }
 
 
@@ -913,19 +868,10 @@ virshDomainLifecycleActionCompleter(vshControl *ctl G_GNUC_UNUSED,
                                     const vshCmd *cmd G_GNUC_UNUSED,
                                     unsigned int flags)
 {
-    g_auto(GStrv) tmp = NULL;
-    size_t i = 0;
-
     virCheckFlags(0, NULL);
 
-    tmp = g_new0(char *, VIR_DOMAIN_LIFECYCLE_ACTION_LAST + 1);
-
-    for (i = 0; i < VIR_DOMAIN_LIFECYCLE_ACTION_LAST; i++) {
-        const char *action = virshDomainLifecycleActionTypeToString(i);
-        tmp[i] = g_strdup(action);
-    }
-
-    return g_steal_pointer(&tmp);
+    return virshEnumComplete(VIR_DOMAIN_LIFECYCLE_ACTION_LAST,
+                             virshDomainLifecycleActionTypeToString);
 }
 
 
@@ -934,19 +880,10 @@ virshCodesetNameCompleter(vshControl *ctl G_GNUC_UNUSED,
                           const vshCmd *cmd G_GNUC_UNUSED,
                           unsigned int flags)
 {
-    g_auto(GStrv) tmp = NULL;
-    size_t i = 0;
-
     virCheckFlags(0, NULL);
 
-    tmp = g_new0(char *, VIR_KEYCODE_SET_LAST + 1);
-
-    for (i = 0; i < VIR_KEYCODE_SET_LAST; i++) {
-        const char *name = virKeycodeSetTypeToString(i);
-        tmp[i] = g_strdup(name);
-    }
-
-    return g_steal_pointer(&tmp);
+    return virshEnumComplete(VIR_KEYCODE_SET_LAST,
+                             virKeycodeSetTypeToString);
 }
 
 
@@ -1064,17 +1001,10 @@ virshDomainCoreDumpFormatCompleter(vshControl *ctl G_GNUC_UNUSED,
                                    const vshCmd *cmd G_GNUC_UNUSED,
                                    unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIR_DOMAIN_CORE_DUMP_FORMAT_LAST + 1);
-
-    for (i = 0; i < VIR_DOMAIN_CORE_DUMP_FORMAT_LAST; i++)
-        ret[i] = g_strdup(virshDomainCoreDumpFormatTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIR_DOMAIN_CORE_DUMP_FORMAT_LAST,
+                             virshDomainCoreDumpFormatTypeToString);
 }
 
 
@@ -1100,17 +1030,10 @@ virshDomainStorageFileFormatCompleter(vshControl *ctl G_GNUC_UNUSED,
                                       const vshCmd *cmd G_GNUC_UNUSED,
                                       unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIR_STORAGE_FILE_LAST + 1);
-
-    for (i = 0; i < VIR_STORAGE_FILE_LAST; i++)
-        ret[i] = g_strdup(virStorageFileFormatTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIR_STORAGE_FILE_LAST,
+                             virStorageFileFormatTypeToString);
 }
 
 
@@ -1119,17 +1042,10 @@ virshDomainNumatuneModeCompleter(vshControl *ctl G_GNUC_UNUSED,
                                  const vshCmd *cmd G_GNUC_UNUSED,
                                  unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIR_DOMAIN_NUMATUNE_MEM_LAST + 1);
-
-    for (i = 0; i < VIR_DOMAIN_NUMATUNE_MEM_LAST; i++)
-        ret[i] = g_strdup(virDomainNumatuneMemModeTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIR_DOMAIN_NUMATUNE_MEM_LAST,
+                             virDomainNumatuneMemModeTypeToString);
 }
 
 
@@ -1138,15 +1054,8 @@ virshDomainDirtyRateCalcModeCompleter(vshControl *ctl G_GNUC_UNUSED,
                                       const vshCmd *cmd G_GNUC_UNUSED,
                                       unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_LAST + 1);
-
-    for (i = 0; i < VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_LAST; i++)
-        ret[i] = g_strdup(virshDomainDirtyRateCalcModeTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_LAST,
+                             virshDomainDirtyRateCalcModeTypeToString);
 }
diff --git a/tools/virsh-completer-host.c b/tools/virsh-completer-host.c
index 3795d1fd3a..40cb687582 100644
--- a/tools/virsh-completer-host.c
+++ b/tools/virsh-completer-host.c
@@ -175,15 +175,8 @@ virshNodeSuspendTargetCompleter(vshControl *ctl G_GNUC_UNUSED,
                                 const vshCmd *cmd G_GNUC_UNUSED,
                                 unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIR_NODE_SUSPEND_TARGET_LAST + 1);
-
-    for (i = 0; i < VIR_NODE_SUSPEND_TARGET_LAST; i++)
-        ret[i] = g_strdup(virshNodeSuspendTargetTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIR_NODE_SUSPEND_TARGET_LAST,
+                             virshNodeSuspendTargetTypeToString);
 }
diff --git a/tools/virsh-completer-nodedev.c b/tools/virsh-completer-nodedev.c
index d10bf2b78c..bf6e809b5a 100644
--- a/tools/virsh-completer-nodedev.c
+++ b/tools/virsh-completer-nodedev.c
@@ -91,17 +91,14 @@ virshNodeDeviceCapabilityNameCompleter(vshControl *ctl,
 {
     g_auto(GStrv) tmp = NULL;
     const char *cap_str = NULL;
-    size_t i = 0;
 
     virCheckFlags(0, NULL);
 
     if (vshCommandOptStringQuiet(ctl, cmd, "cap", &cap_str) < 0)
         return NULL;
 
-    tmp = g_new0(char *, VIR_NODE_DEV_CAP_LAST + 1);
-
-    for (i = 0; i < VIR_NODE_DEV_CAP_LAST; i++)
-        tmp[i] = g_strdup(virNodeDevCapTypeToString(i));
+    tmp = virshEnumComplete(VIR_NODE_DEV_CAP_LAST,
+                            virNodeDevCapTypeToString);
 
     return virshCommaStringListComplete(cap_str, (const char **)tmp);
 }
diff --git a/tools/virsh-completer-pool.c b/tools/virsh-completer-pool.c
index 84e9d6cc5a..1a966d95b9 100644
--- a/tools/virsh-completer-pool.c
+++ b/tools/virsh-completer-pool.c
@@ -94,17 +94,14 @@ virshPoolTypeCompleter(vshControl *ctl,
 {
     g_auto(GStrv) tmp = NULL;
     const char *type_str = NULL;
-    size_t i = 0;
 
     virCheckFlags(0, NULL);
 
     if (vshCommandOptStringQuiet(ctl, cmd, "type", &type_str) < 0)
         return NULL;
 
-    tmp = g_new0(char *, VIR_STORAGE_POOL_LAST + 1);
-
-    for (i = 0; i < VIR_STORAGE_POOL_LAST; i++)
-        tmp[i] = g_strdup(virStoragePoolTypeToString(i));
+    tmp = virshEnumComplete(VIR_STORAGE_POOL_LAST,
+                            virStoragePoolTypeToString);
 
     return virshCommaStringListComplete(type_str, (const char **)tmp);
 }
diff --git a/tools/virsh-completer-volume.c b/tools/virsh-completer-volume.c
index bed45fa1ca..a1ebadccac 100644
--- a/tools/virsh-completer-volume.c
+++ b/tools/virsh-completer-volume.c
@@ -123,15 +123,8 @@ virshStorageVolWipeAlgorithmCompleter(vshControl *ctl G_GNUC_UNUSED,
                                       const vshCmd *cmd G_GNUC_UNUSED,
                                       unsigned int flags)
 {
-    char **ret = NULL;
-    size_t i;
-
     virCheckFlags(0, NULL);
 
-    ret = g_new0(char *, VIR_STORAGE_VOL_WIPE_ALG_LAST + 1);
-
-    for (i = 0; i < VIR_STORAGE_VOL_WIPE_ALG_LAST; i++)
-        ret[i] = g_strdup(virshStorageVolWipeAlgorithmTypeToString(i));
-
-    return ret;
+    return virshEnumComplete(VIR_STORAGE_VOL_WIPE_ALG_LAST,
+                             virshStorageVolWipeAlgorithmTypeToString);
 }