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

antonvw / wex / 24937057866

25 Apr 2026 05:57PM UTC coverage: 64.281%. Remained the same
24937057866

push

github

antonvw
prevent slicing

18754 of 32047 branches covered (58.52%)

Branch coverage included in aggregate %.

14957 of 20396 relevant lines covered (73.33%)

1457.91 hits per line

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

87.11
/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-2026 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,276✔
17
  ex*                ex,
18
  const std::string& text,
19
  parse_t            type)
2,276✔
20
  : command_parser_data(text)
21
  , m_ex(ex)
2,276✔
22
  , m_is_ok(m_text.empty() ? false : parse(type))
2,276✔
23
{
24
}
2,276✔
25

26
wex::command_parser_data wex::command_parser::get_parsed_data() const
438✔
27
{
28
  // this is added to prevent slicing
29
  return command_parser_data(*this);
438✔
30
}
31

32
bool wex::command_parser::parse(parse_t type)
2,275✔
33
{
34
  if (m_text.starts_with(ex_command::selection_range()))
2,275✔
35
  {
36
    if (!parse_selection())
14✔
37
    {
38
      return false;
2✔
39
    }
40
  }
41
  else if (!parse_other())
2,261!
42
  {
43
    return false;
×
44
  }
45

46
  if (type == parse_t::CHECK)
2,273✔
47
  {
48
    return true;
3✔
49
  }
50

51
  try
52
  {
53
    switch (m_type)
2,270!
54
    {
55
      case address_t::NO_ADDR:
85✔
56
      {
57
        m_range.clear();
85✔
58
        const auto line(address(m_ex, m_text).get_line());
85✔
59
        return m_ex->get_stc()->inject(data::control().line(line));
85✔
60
      }
61

62
      case address_t::ONE_ADDR:
1,735✔
63
        return address(m_ex).parse(*this);
1,735✔
64

65
      case address_t::TWO_ADDR:
450✔
66
        if (info_message_t im; !addressrange(m_ex, m_range).parse(*this, im))
450✔
67
        {
68
          return false;
12✔
69
        }
70
        else if (im != info_message_t::NONE)
438✔
71
        {
72
          m_ex->info_message(m_ex->register_text(), im);
107✔
73
        }
74
        break;
438✔
75

76
      default:
×
77
        assert(0);
×
78
    }
79
  }
80
  catch (std::exception& e)
×
81
  {
82
    log(e) << m_cmd;
×
83
    return false;
×
84
  }
×
85

86
  m_ex->m_command_parsed_data = get_parsed_data();
438✔
87

88
  return true;
438✔
89
}
90

91
bool wex::command_parser::parse_other()
2,261✔
92
{
93
  ex_expansion(m_ex, m_text);
2,261✔
94

95
  // Addressing in ex.
96
  // See also address::get_line
97
  const std::string addr(
98
    // (1) . (2) $ (3) decimal number, + or - (7)
99
    "[\\.\\$0-9\\+\\-]+|"
100
    // (4) marker
101
    "'[a-z]|"
102
    // (5) (6) regex find, non-greedy!
103
    "[-+]?[0-9]*[\\?/].*?[\\?/][-+]?[0-9]*");
2,261✔
104

105
  const auto& cmds_1addr(address(m_ex).regex_commands());
2,261✔
106
  const auto& cmds_2addr(addressrange(m_ex).regex_commands());
2,261✔
107

108
  if (
2,261✔
109
    regex v(
110
      {// 2addr % range
111
       {"^%" + cmds_2addr,
×
112
        [&](const regex::match_t& m)
×
113
        {
114
          m_type  = address_t::TWO_ADDR;
39✔
115
          m_range = "%";
39✔
116
          m_cmd   = m[0];
39✔
117
          m_text  = m[1];
39✔
118
        }},
39✔
119
       // 1addr (or none)
120
       {"^(" + addr + ")?" + cmds_1addr,
4,522✔
121
        [&](const regex::match_t& m)
×
122
        {
123
          m_type  = address_t::ONE_ADDR;
1,735✔
124
          m_range = m[0];
1,735✔
125
          m_cmd   = m[1];
1,735✔
126
          m_text  = boost::algorithm::trim_left_copy(m[2]);
1,735✔
127
          log::trace("ex 1addr") << m_range;
1,735✔
128
        }},
1,735✔
129
       // 2addr
130
       {"^(" + addr + "),(" + addr + ")" + cmds_2addr,
4,522✔
131
        [&](const regex::match_t& m)
×
132
        {
133
          m_type  = address_t::TWO_ADDR;
122✔
134
          m_range = m[0] + "," + m[1];
122✔
135
          m_cmd   = m[2];
122✔
136
          m_text  = m[3];
122✔
137
          log::trace("ex 2addr") << m_range;
122✔
138
        }},
122✔
139
       // 2addr
140
       {"^(" + addr + ")?" + cmds_2addr,
4,522✔
141
        [&](const regex::match_t& m)
2,261✔
142
        {
143
          m_type  = address_t::TWO_ADDR;
279✔
144
          m_range = m[0];
279✔
145
          m_cmd   = m[1];
279✔
146
          m_text  = m[2];
279✔
147
          log::trace("ex 2addr") << m_range;
279✔
148
        }}});
13,845!
149
    v.match(m_text) <= 1)
2,261✔
150
  {
151
    m_type = address_t::NO_ADDR;
86✔
152
  }
2,261✔
153

154
  if (m_range.empty() && m_cmd != "!")
2,261✔
155
  {
156
    m_range =
157
      (m_cmd.starts_with("g") || m_cmd == "v" || m_cmd == "w" ? "%" : ".");
1,839✔
158
  }
159

160
  return true;
2,261✔
161
}
11,305!
162

163
bool wex::command_parser::parse_selection()
14✔
164
{
165
  if (m_ex->get_stc()->get_selected_text().empty())
14✔
166
  {
167
    return false;
1✔
168
  }
169

170
  const auto& cmds_2addr(addressrange(m_ex).regex_commands());
13✔
171

172
  if (
13✔
173
    regex r(
174
      {{ex_command::selection_range() + cmds_2addr,
26✔
175
        [&](const regex::match_t& m)
13✔
176
        {
177
          m_type  = address_t::TWO_ADDR;
12✔
178
          m_range = ex_command::selection_range();
12✔
179
          m_cmd   = m[0];
12✔
180
          m_text  = m[1];
12✔
181
          log::trace("ex selection") << m_range;
12✔
182
        }}});
51!
183
    r.match(m_text) == 2)
13✔
184
  {
185
    return true;
12✔
186
  }
13✔
187

188
  return false;
1✔
189
}
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