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

antonvw / wex / 15349103000

30 May 2025 02:33PM UTC coverage: 28.052% (-30.9%) from 58.951%
15349103000

push

github

antonvw
fixing the segfault

7896 of 31160 branches covered (25.34%)

Branch coverage included in aggregate %.

6430 of 19909 relevant lines covered (32.3%)

64.4 hits per line

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

56.82
/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-2024 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/factory/control.h>
13
#include <wex/syntax/stc.h>
14

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

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

39
  if (type == parse_t::CHECK)
5✔
40
  {
41
    return true;
3✔
42
  }
43

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

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

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

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

79
  return true;
1✔
80
}
81

82
bool wex::command_parser::parse_other()
5✔
83
{
84
  marker_and_register_expansion(m_ex, m_text);
5✔
85

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

96
  const auto& cmds_1addr(address(m_ex).regex_commands());
5✔
97
  const auto& cmds_2addr(addressrange(m_ex).regex_commands());
5✔
98

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

143
  if (m_range.empty() && m_cmd != "!")
5✔
144
  {
145
    m_range =
146
      (m_cmd.starts_with("g") || m_cmd == "v" || m_cmd == "w" ? "%" : ".");
2!
147
  }
148

149
  return true;
5✔
150
}
25!
151

152
bool wex::command_parser::parse_selection()
×
153
{
154
  if (m_ex->get_stc()->get_selected_text().empty())
×
155
  {
156
    return false;
×
157
  }
158

159
  const auto& cmds_2addr(addressrange(m_ex).regex_commands());
×
160

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

176
  return false;
×
177
}
×
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