• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

antonvw / wex / 23084300327

14 Mar 2026 08:29AM UTC coverage: 64.122% (-0.03%) from 64.153%
23084300327

push

github

web-flow
Merge to master (#1190)

* started with 26.04, added more const to chrono (#1012)

* 1013 add regex option to git grep (#1014)

* added regex option to git grep

* fixed lint error

* simplify get_branch (#1017)

* log_none respects trace level logging (#1019)

* 1020 allow skip micro and revision number (#1021)

* allow explicitly excluding micro and revision number

* mention change

* update version dialog as well

* 1015 make msw debug artefact for feature branches (#1022)

* use debug build for feature branches, and add sample as artefact

* added setting bevOverwrite

* use older version

* use github variables

* added quotes

* fix name

* use github.ref_name

* added script to get build config, use in ci-msw.yml

* remove trailing whitespace

* fixed compile error (?)

* updated condition

* updated condition

* added allow-failure

* use continue on error

* 1023 add url for open group base specs (#1024)

* added url for open group base specs

* fxing lint

* improve opening links (#1026)

* 1027 cmdline improve (#1028)

* cmdline improvement on options

* updated option for version

* use more std::ranges::contains (#1030)

* improve regex to find paths in lines (#1032)

* moved get_abbreviations from test library to test ex (#1034)

* use ProcessPendingEvents instead of wxYield (#1037)

* fix git admin dir in tests (#1039)

* 1035 fix crash on windows for git show (#1040)

* reenabled the execute-show test for msw, and added mayfail flag

* some test updates

* reenabled other windows tests for wex::vcs_entry

* upgrade boost version, clearified names

* try fixing crash, in debug mode it is OK

* 1041 fix hypertext auto complete (#1043)

* fixed hypertext complete, upgrade boost on ci ubuntu

* fix linter error

* fix ranges::all_of warning (#1045)

* fix recording inc macro, by using control k for it (#1046)

* removed K accelerator (#1048)

* 1049 no auto in public interface (#1050)

* no auto in public interface

* no auto in public in... (continued)

18596 of 31859 branches covered (58.37%)

Branch coverage included in aggregate %.

14825 of 20262 relevant lines covered (73.17%)

1490.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.94
/src/ex/command-parser.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
// Name:      command-parser.cpp
3
// Purpose:   Implementation of class wex::command_parser
4
// Author:    Anton van Wezenbeek
5
// Copyright: (c) 2021-2025 Anton van Wezenbeek
6
////////////////////////////////////////////////////////////////////////////////
7

8
#include <boost/algorithm/string.hpp>
9
#include <wex/core/log.h>
10
#include <wex/ex/addressrange.h>
11
#include <wex/ex/command-parser.h>
12
#include <wex/ex/ex.h>
13
#include <wex/factory/control.h>
14
#include <wex/syntax/stc.h>
15

16
wex::command_parser::command_parser(
2,274✔
17
  ex*                ex,
18
  const std::string& text,
19
  parse_t            type)
2,274✔
20
  : command_parser_data(text)
21
  , m_ex(ex)
2,274✔
22
{
23
  m_is_ok = m_text.empty() ? false : parse(type);
2,274✔
24
}
2,274✔
25

26
bool wex::command_parser::parse(parse_t type)
2,273✔
27
{
28
  if (m_text.starts_with(ex_command::selection_range()))
2,273✔
29
  {
30
    if (!parse_selection())
14✔
31
    {
32
      return false;
2✔
33
    }
34
  }
35
  else if (!parse_other())
2,259!
36
  {
37
    return false;
×
38
  }
39

40
  if (type == parse_t::CHECK)
2,271✔
41
  {
42
    return true;
3✔
43
  }
44

45
  try
46
  {
47
    switch (m_type)
2,268!
48
    {
49
      case address_t::NO_ADDR:
84✔
50
      {
51
        m_range.clear();
84✔
52
        const auto line(address(m_ex, m_text).get_line());
84✔
53
        return m_ex->get_stc()->inject(data::control().line(line));
84✔
54
      }
55

56
      case address_t::ONE_ADDR:
1,734✔
57
        return address(m_ex).parse(*this);
1,734✔
58

59
      case address_t::TWO_ADDR:
450✔
60
        if (info_message_t im; !addressrange(m_ex, m_range).parse(*this, im))
450✔
61
        {
62
          return false;
12✔
63
        }
64
        else if (im != info_message_t::NONE)
438✔
65
        {
66
          m_ex->info_message(m_ex->register_text(), im);
107✔
67
        }
68
        break;
438✔
69

70
      default:
×
71
        assert(0);
×
72
    }
73
  }
74
  catch (std::exception& e)
×
75
  {
76
    log(e) << m_cmd;
×
77
    return false;
×
78
  }
×
79

80
  m_ex->m_command_parsed_data = *this;
438✔
81

82
  return true;
438✔
83
}
84

85
bool wex::command_parser::parse_other()
2,259✔
86
{
87
  marker_and_register_expansion(m_ex, m_text);
2,259✔
88

89
  // Addressing in ex.
90
  // See also address::get_line
91
  const std::string addr(
92
    // (1) . (2) $ (3) decimal number, + or - (7)
93
    "[\\.\\$0-9\\+\\-]+|"
94
    // (4) marker
95
    "'[a-z]|"
96
    // (5) (6) regex find, non-greedy!
97
    "[-+]?[0-9]*[\\?/].*?[\\?/][-+]?[0-9]*");
2,259✔
98

99
  const auto& cmds_1addr(address(m_ex).regex_commands());
2,259✔
100
  const auto& cmds_2addr(addressrange(m_ex).regex_commands());
2,259✔
101

102
  if (regex v({// 2addr % range
2,259✔
103
               {"^%" + cmds_2addr,
×
104
                [&](const regex::match_t& m)
×
105
                {
106
                  m_type  = address_t::TWO_ADDR;
39✔
107
                  m_range = "%";
39✔
108
                  m_cmd   = m[0];
39✔
109
                  m_text  = m[1];
39✔
110
                }},
39✔
111
               // 1addr (or none)
112
               {"^(" + addr + ")?" + cmds_1addr,
4,518✔
113
                [&](const regex::match_t& m)
×
114
                {
115
                  m_type  = address_t::ONE_ADDR;
1,734✔
116
                  m_range = m[0];
1,734✔
117
                  m_cmd   = m[1];
1,734✔
118
                  m_text  = boost::algorithm::trim_left_copy(m[2]);
1,734✔
119
                  log::trace("ex 1addr") << m_range;
1,734✔
120
                }},
1,734✔
121
               // 2addr
122
               {"^(" + addr + "),(" + addr + ")" + cmds_2addr,
4,518✔
123
                [&](const regex::match_t& m)
×
124
                {
125
                  m_type  = address_t::TWO_ADDR;
122✔
126
                  m_range = m[0] + "," + m[1];
122✔
127
                  m_cmd   = m[2];
122✔
128
                  m_text  = m[3];
122✔
129
                  log::trace("ex 2addr") << m_range;
122✔
130
                }},
122✔
131
               // 2addr
132
               {"^(" + addr + ")?" + cmds_2addr,
4,518✔
133
                [&](const regex::match_t& m)
2,259✔
134
                {
135
                  m_type  = address_t::TWO_ADDR;
279✔
136
                  m_range = m[0];
279✔
137
                  m_cmd   = m[1];
279✔
138
                  m_text  = m[2];
279✔
139
                  log::trace("ex 2addr") << m_range;
279✔
140
                }}});
13,833!
141
      v.match(m_text) <= 1)
2,259✔
142
  {
143
    m_type = address_t::NO_ADDR;
85✔
144
  }
2,259✔
145

146
  if (m_range.empty() && m_cmd != "!")
2,259✔
147
  {
148
    m_range =
149
      (m_cmd.starts_with("g") || m_cmd == "v" || m_cmd == "w" ? "%" : ".");
1,837✔
150
  }
151

152
  return true;
2,259✔
153
}
11,295!
154

155
bool wex::command_parser::parse_selection()
14✔
156
{
157
  if (m_ex->get_stc()->get_selected_text().empty())
14✔
158
  {
159
    return false;
1✔
160
  }
161

162
  const auto& cmds_2addr(addressrange(m_ex).regex_commands());
13✔
163

164
  if (regex r(
13✔
165
        {{ex_command::selection_range() + cmds_2addr,
26✔
166
          [&](const regex::match_t& m)
13✔
167
          {
168
            m_type  = address_t::TWO_ADDR;
12✔
169
            m_range = ex_command::selection_range();
12✔
170
            m_cmd   = m[0];
12✔
171
            m_text  = m[1];
12✔
172
            log::trace("ex selection") << m_range;
12✔
173
          }}});
51!
174
      r.match(m_text) == 2)
13✔
175
  {
176
    return true;
12✔
177
  }
13✔
178

179
  return false;
1✔
180
}
39!
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc