mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 7.4.1042
Problem: g-CTRL-G shows the word count, but there is no way to get the word count in a script. Solution: Add the wordcount() function. (Christian Brabandt)
This commit is contained in:
parent
022b896592
commit
ed767a2073
@ -78,7 +78,9 @@ g CTRL-G Prints the current position of the cursor in five
|
|||||||
than one position on the screen (<Tab> or special
|
than one position on the screen (<Tab> or special
|
||||||
character), both the "real" column and the screen
|
character), both the "real" column and the screen
|
||||||
column are shown, separated with a dash.
|
column are shown, separated with a dash.
|
||||||
See also 'ruler' option. {not in Vi}
|
Also see the 'ruler' option and the |wordcount()|
|
||||||
|
function.
|
||||||
|
{not in Vi}
|
||||||
|
|
||||||
*v_g_CTRL-G*
|
*v_g_CTRL-G*
|
||||||
{Visual}g CTRL-G Similar to "g CTRL-G", but Word, Character, Line, and
|
{Visual}g CTRL-G Similar to "g CTRL-G", but Word, Character, Line, and
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*eval.txt* For Vim version 7.4. Last change: 2016 Jan 02
|
*eval.txt* For Vim version 7.4. Last change: 2016 Jan 03
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -2075,6 +2075,7 @@ winrestcmd() String returns command to restore window sizes
|
|||||||
winrestview( {dict}) none restore view of current window
|
winrestview( {dict}) none restore view of current window
|
||||||
winsaveview() Dict save view of current window
|
winsaveview() Dict save view of current window
|
||||||
winwidth( {nr}) Number width of window {nr}
|
winwidth( {nr}) Number width of window {nr}
|
||||||
|
wordcount() Dict get byte/char/word statistics
|
||||||
writefile( {list}, {fname} [, {flags}])
|
writefile( {list}, {fname} [, {flags}])
|
||||||
Number write list of lines to file {fname}
|
Number write list of lines to file {fname}
|
||||||
xor( {expr}, {expr}) Number bitwise XOR
|
xor( {expr}, {expr}) Number bitwise XOR
|
||||||
@ -6744,6 +6745,28 @@ winwidth({nr}) *winwidth()*
|
|||||||
: exe "normal 50\<C-W>|"
|
: exe "normal 50\<C-W>|"
|
||||||
:endif
|
:endif
|
||||||
<
|
<
|
||||||
|
wordcount() *wordcount()*
|
||||||
|
The result is a dictionary of byte/chars/word statistics for
|
||||||
|
the current buffer. This is the same info as provided by
|
||||||
|
|g_CTRL-G|
|
||||||
|
The return value includes:
|
||||||
|
bytes Number of bytes in the buffer
|
||||||
|
chars Number of chars in the buffer
|
||||||
|
words Number of words in the buffer
|
||||||
|
cursor_bytes Number of bytes before cursor position
|
||||||
|
(not in Visual mode)
|
||||||
|
cursor_chars Number of chars before cursor position
|
||||||
|
(not in Visual mode)
|
||||||
|
cursor_words Number of words before cursor position
|
||||||
|
(not in Visual mode)
|
||||||
|
visual_bytes Number of bytes visually selected
|
||||||
|
(only in Visual mode)
|
||||||
|
visual_chars Number of chars visually selected
|
||||||
|
(only in Visual mode)
|
||||||
|
visual_words Number of chars visually selected
|
||||||
|
(only in Visual mode)
|
||||||
|
|
||||||
|
|
||||||
*writefile()*
|
*writefile()*
|
||||||
writefile({list}, {fname} [, {flags}])
|
writefile({list}, {fname} [, {flags}])
|
||||||
Write |List| {list} to file {fname}. Each list item is
|
Write |List| {list} to file {fname}. Each list item is
|
||||||
|
@ -923,6 +923,7 @@ Various: *various-functions*
|
|||||||
mzeval() evaluate |MzScheme| expression
|
mzeval() evaluate |MzScheme| expression
|
||||||
py3eval() evaluate Python expression (|+python3|)
|
py3eval() evaluate Python expression (|+python3|)
|
||||||
pyeval() evaluate Python expression (|+python|)
|
pyeval() evaluate Python expression (|+python|)
|
||||||
|
wordcount() get byte/word/char count of buffer
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*41.7* Defining a function
|
*41.7* Defining a function
|
||||||
|
15
src/eval.c
15
src/eval.c
@ -780,6 +780,7 @@ static void f_winrestview __ARGS((typval_T *argvars, typval_T *rettv));
|
|||||||
static void f_winsaveview __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_winsaveview __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
|
static void f_wordcount __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
static void f_xor __ARGS((typval_T *argvars, typval_T *rettv));
|
static void f_xor __ARGS((typval_T *argvars, typval_T *rettv));
|
||||||
|
|
||||||
static int list2fpos __ARGS((typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp));
|
static int list2fpos __ARGS((typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp));
|
||||||
@ -8387,6 +8388,7 @@ static struct fst
|
|||||||
{"winrestview", 1, 1, f_winrestview},
|
{"winrestview", 1, 1, f_winrestview},
|
||||||
{"winsaveview", 0, 0, f_winsaveview},
|
{"winsaveview", 0, 0, f_winsaveview},
|
||||||
{"winwidth", 1, 1, f_winwidth},
|
{"winwidth", 1, 1, f_winwidth},
|
||||||
|
{"wordcount", 0, 0, f_wordcount},
|
||||||
{"writefile", 2, 3, f_writefile},
|
{"writefile", 2, 3, f_writefile},
|
||||||
{"xor", 2, 2, f_xor},
|
{"xor", 2, 2, f_xor},
|
||||||
};
|
};
|
||||||
@ -20219,6 +20221,19 @@ f_winwidth(argvars, rettv)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "wordcount()" function
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
f_wordcount(argvars, rettv)
|
||||||
|
typval_T *argvars UNUSED;
|
||||||
|
typval_T *rettv;
|
||||||
|
{
|
||||||
|
if (rettv_dict_alloc(rettv) == FAIL)
|
||||||
|
return;
|
||||||
|
cursor_pos_info(rettv->vval.v_dict);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write list of strings to file
|
* Write list of strings to file
|
||||||
*/
|
*/
|
||||||
|
@ -8270,7 +8270,7 @@ nv_g_cmd(cap)
|
|||||||
* "g CTRL-G": display info about cursor position
|
* "g CTRL-G": display info about cursor position
|
||||||
*/
|
*/
|
||||||
case Ctrl_G:
|
case Ctrl_G:
|
||||||
cursor_pos_info();
|
cursor_pos_info(NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
45
src/ops.c
45
src/ops.c
@ -6963,15 +6963,18 @@ line_count_info(line, wc, cc, limit, eol_size)
|
|||||||
* Give some info about the position of the cursor (for "g CTRL-G").
|
* Give some info about the position of the cursor (for "g CTRL-G").
|
||||||
* In Visual mode, give some info about the selected region. (In this case,
|
* In Visual mode, give some info about the selected region. (In this case,
|
||||||
* the *_count_cursor variables store running totals for the selection.)
|
* the *_count_cursor variables store running totals for the selection.)
|
||||||
|
* When "dict" is not NULL store the info there instead of showing it.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
cursor_pos_info()
|
cursor_pos_info(dict)
|
||||||
|
dict_T *dict;
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
char_u buf1[50];
|
char_u buf1[50];
|
||||||
char_u buf2[40];
|
char_u buf2[40];
|
||||||
linenr_T lnum;
|
linenr_T lnum;
|
||||||
long byte_count = 0;
|
long byte_count = 0;
|
||||||
|
long bom_count = 0;
|
||||||
long byte_count_cursor = 0;
|
long byte_count_cursor = 0;
|
||||||
long char_count = 0;
|
long char_count = 0;
|
||||||
long char_count_cursor = 0;
|
long char_count_cursor = 0;
|
||||||
@ -6988,8 +6991,12 @@ cursor_pos_info()
|
|||||||
* Compute the length of the file in characters.
|
* Compute the length of the file in characters.
|
||||||
*/
|
*/
|
||||||
if (curbuf->b_ml.ml_flags & ML_EMPTY)
|
if (curbuf->b_ml.ml_flags & ML_EMPTY)
|
||||||
|
{
|
||||||
|
if (dict == NULL)
|
||||||
{
|
{
|
||||||
MSG(_(no_lines_msg));
|
MSG(_(no_lines_msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -7122,6 +7129,8 @@ cursor_pos_info()
|
|||||||
if (!curbuf->b_p_eol && (curbuf->b_p_bin || !curbuf->b_p_fixeol))
|
if (!curbuf->b_p_eol && (curbuf->b_p_bin || !curbuf->b_p_fixeol))
|
||||||
byte_count -= eol_size;
|
byte_count -= eol_size;
|
||||||
|
|
||||||
|
if (dict == NULL)
|
||||||
|
{
|
||||||
if (VIsual_active)
|
if (VIsual_active)
|
||||||
{
|
{
|
||||||
if (VIsual_mode == Ctrl_V && curwin->w_curswant < MAXCOL)
|
if (VIsual_mode == Ctrl_V && curwin->w_curswant < MAXCOL)
|
||||||
@ -7179,17 +7188,39 @@ cursor_pos_info()
|
|||||||
char_count_cursor, char_count,
|
char_count_cursor, char_count,
|
||||||
byte_count_cursor, byte_count);
|
byte_count_cursor, byte_count);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FEAT_MBYTE
|
|
||||||
byte_count = bomb_size();
|
|
||||||
if (byte_count > 0)
|
|
||||||
sprintf((char *)IObuff + STRLEN(IObuff), _("(+%ld for BOM)"),
|
|
||||||
byte_count);
|
|
||||||
#endif
|
|
||||||
/* Don't shorten this message, the user asked for it. */
|
/* Don't shorten this message, the user asked for it. */
|
||||||
|
#ifdef FEAT_MBYTE
|
||||||
|
bom_count = bomb_size();
|
||||||
|
if (bom_count > 0)
|
||||||
|
sprintf((char *)IObuff + STRLEN(IObuff), _("(+%ld for BOM)"),
|
||||||
|
bom_count);
|
||||||
|
#endif
|
||||||
|
if (dict == NULL)
|
||||||
|
{
|
||||||
p = p_shm;
|
p = p_shm;
|
||||||
p_shm = (char_u *)"";
|
p_shm = (char_u *)"";
|
||||||
msg(IObuff);
|
msg(IObuff);
|
||||||
p_shm = p;
|
p_shm = p;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (dict != NULL)
|
||||||
|
{
|
||||||
|
dict_add_nr_str(dict, "words", (long)word_count, NULL);
|
||||||
|
dict_add_nr_str(dict, "chars", (long)char_count, NULL);
|
||||||
|
dict_add_nr_str(dict, "bytes", (long)byte_count + bom_count, NULL);
|
||||||
|
if (VIsual_active)
|
||||||
|
{
|
||||||
|
dict_add_nr_str(dict, "visual_bytes", (long)byte_count_cursor, NULL);
|
||||||
|
dict_add_nr_str(dict, "visual_chars", (long)char_count_cursor, NULL);
|
||||||
|
dict_add_nr_str(dict, "visual_words", (long)word_count_cursor, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict_add_nr_str(dict, "cursor_bytes", (long)byte_count_cursor, NULL);
|
||||||
|
dict_add_nr_str(dict, "cursor_chars", (long)char_count_cursor, NULL);
|
||||||
|
dict_add_nr_str(dict, "cursor_words", (long)word_count_cursor, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,5 +58,5 @@ void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_appe
|
|||||||
void write_reg_contents_lst __ARGS((int name, char_u **strings, int maxlen, int must_append, int yank_type, long block_len));
|
void write_reg_contents_lst __ARGS((int name, char_u **strings, int maxlen, int must_append, int yank_type, long block_len));
|
||||||
void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len));
|
void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len));
|
||||||
void clear_oparg __ARGS((oparg_T *oap));
|
void clear_oparg __ARGS((oparg_T *oap));
|
||||||
void cursor_pos_info __ARGS((void));
|
void cursor_pos_info __ARGS((dict_T *eval));
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -120,6 +120,7 @@ SCRIPTS_ALL = \
|
|||||||
test_tagcase.out \
|
test_tagcase.out \
|
||||||
test_textobjects.out \
|
test_textobjects.out \
|
||||||
test_utf8.out \
|
test_utf8.out \
|
||||||
|
test_wordcount.out \
|
||||||
test_writefile.out
|
test_writefile.out
|
||||||
|
|
||||||
|
|
||||||
|
125
src/testdir/test_wordcount.in
Normal file
125
src/testdir/test_wordcount.in
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
Test for wordcount() function
|
||||||
|
|
||||||
|
STARTTEST
|
||||||
|
:so small.vim
|
||||||
|
:so mbyte.vim
|
||||||
|
:set enc=utf8
|
||||||
|
:new
|
||||||
|
:fu DoRecordWin(...)
|
||||||
|
: wincmd k
|
||||||
|
: if exists("a:1")
|
||||||
|
: call cursor(a:1)
|
||||||
|
: endif
|
||||||
|
: let result=[]
|
||||||
|
: call add(result, g:test)
|
||||||
|
: call add(result, getline(1, '$'))
|
||||||
|
: call add(result, wordcount())
|
||||||
|
: wincmd j
|
||||||
|
: return result
|
||||||
|
:endfu
|
||||||
|
:fu PutInWindow(args)
|
||||||
|
: wincmd k
|
||||||
|
: %d _
|
||||||
|
: call append(1, a:args)
|
||||||
|
: wincmd j
|
||||||
|
:endfu
|
||||||
|
:fu Log()
|
||||||
|
: $put ='----'
|
||||||
|
: $put =remove(g:log,0)
|
||||||
|
: $put =string(g:log)
|
||||||
|
:endfu
|
||||||
|
:fu! STL()
|
||||||
|
: if mode() =~? 'V'
|
||||||
|
: let g:visual_stat=wordcount()
|
||||||
|
: endif
|
||||||
|
: return string(wordcount())
|
||||||
|
:endfu
|
||||||
|
:let g:test="Test 1: empty window"
|
||||||
|
:let log=DoRecordWin()
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 2: some words, cursor at start"
|
||||||
|
:call PutInWindow('one two three')
|
||||||
|
:let log=DoRecordWin([1,1,0])
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 3: some words, cursor at end"
|
||||||
|
:call PutInWindow('one two three')
|
||||||
|
:let log=DoRecordWin([2,99,0])
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 4: some words, cursor at end, ve=all"
|
||||||
|
:set ve=all
|
||||||
|
:call PutInWindow('one two three')
|
||||||
|
:let log=DoRecordWin([2,99,0])
|
||||||
|
:call Log()
|
||||||
|
:set ve=
|
||||||
|
:"
|
||||||
|
:let g:test="Test 5: several lines with words"
|
||||||
|
:call PutInWindow(['one two three', 'one two three', 'one two three'])
|
||||||
|
:let log=DoRecordWin([4,99,0])
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 6: one line with BOM set"
|
||||||
|
:call PutInWindow('one two three')
|
||||||
|
:wincmd k
|
||||||
|
:set bomb
|
||||||
|
:w! Xtest
|
||||||
|
:wincmd j
|
||||||
|
:let log=DoRecordWin([2,99,0])
|
||||||
|
:call Log()
|
||||||
|
:wincmd k
|
||||||
|
:set nobomb
|
||||||
|
:w!
|
||||||
|
:wincmd j
|
||||||
|
:"
|
||||||
|
:let g:test="Test 7: one line with multibyte words"
|
||||||
|
:call PutInWindow(['Äne M¤ne Müh'])
|
||||||
|
:let log=DoRecordWin([2,99,0])
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 8: several lines with multibyte words"
|
||||||
|
:call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])
|
||||||
|
:let log=DoRecordWin([3,99,0])
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 9: visual mode, complete buffer"
|
||||||
|
:call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])
|
||||||
|
:wincmd k
|
||||||
|
:set ls=2 stl=%{STL()}
|
||||||
|
:" start visual mode quickly and select complete buffer
|
||||||
|
:0
|
||||||
|
V2jy
|
||||||
|
:set stl= ls=1
|
||||||
|
:let log=DoRecordWin([3,99,0])
|
||||||
|
:let log[2]=g:visual_stat
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 10: visual mode (empty)"
|
||||||
|
:call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])
|
||||||
|
:wincmd k
|
||||||
|
:set ls=2 stl=%{STL()}
|
||||||
|
:" start visual mode quickly and select complete buffer
|
||||||
|
:0
|
||||||
|
v$y
|
||||||
|
:set stl= ls=1
|
||||||
|
:let log=DoRecordWin([3,99,0])
|
||||||
|
:let log[2]=g:visual_stat
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:let g:test="Test 11: visual mode, single line"
|
||||||
|
:call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])
|
||||||
|
:wincmd k
|
||||||
|
:set ls=2 stl=%{STL()}
|
||||||
|
:" start visual mode quickly and select complete buffer
|
||||||
|
:2
|
||||||
|
0v$y
|
||||||
|
:set stl= ls=1
|
||||||
|
:let log=DoRecordWin([3,99,0])
|
||||||
|
:let log[2]=g:visual_stat
|
||||||
|
:call Log()
|
||||||
|
:"
|
||||||
|
:/^RESULT test/,$w! test.out
|
||||||
|
:qa!
|
||||||
|
ENDTEST
|
||||||
|
RESULT test:
|
34
src/testdir/test_wordcount.ok
Normal file
34
src/testdir/test_wordcount.ok
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
RESULT test:
|
||||||
|
----
|
||||||
|
Test 1: empty window
|
||||||
|
[[''], {'chars': 0, 'cursor_chars': 0, 'words': 0, 'cursor_words': 0, 'bytes': 0, 'cursor_bytes': 0}]
|
||||||
|
----
|
||||||
|
Test 2: some words, cursor at start
|
||||||
|
[['', 'one two three'], {'chars': 15, 'cursor_chars': 1, 'words': 3, 'cursor_words': 0, 'bytes': 15, 'cursor_bytes': 1}]
|
||||||
|
----
|
||||||
|
Test 3: some words, cursor at end
|
||||||
|
[['', 'one two three'], {'chars': 15, 'cursor_chars': 14, 'words': 3, 'cursor_words': 3, 'bytes': 15, 'cursor_bytes': 14}]
|
||||||
|
----
|
||||||
|
Test 4: some words, cursor at end, ve=all
|
||||||
|
[['', 'one two three'], {'chars': 15, 'cursor_chars': 15, 'words': 3, 'cursor_words': 3, 'bytes': 15, 'cursor_bytes': 15}]
|
||||||
|
----
|
||||||
|
Test 5: several lines with words
|
||||||
|
[['', 'one two three', 'one two three', 'one two three'], {'chars': 43, 'cursor_chars': 42, 'words': 9, 'cursor_words': 9, 'bytes': 43, 'cursor_bytes': 42}]
|
||||||
|
----
|
||||||
|
Test 6: one line with BOM set
|
||||||
|
[['', 'one two three'], {'chars': 15, 'cursor_chars': 14, 'words': 3, 'cursor_words': 3, 'bytes': 18, 'cursor_bytes': 14}]
|
||||||
|
----
|
||||||
|
Test 7: one line with multibyte words
|
||||||
|
[['', 'Äne M¤ne Müh'], {'chars': 14, 'cursor_chars': 13, 'words': 3, 'cursor_words': 3, 'bytes': 17, 'cursor_bytes': 16}]
|
||||||
|
----
|
||||||
|
Test 8: several lines with multibyte words
|
||||||
|
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'cursor_chars': 31, 'words': 7, 'cursor_words': 7, 'bytes': 36, 'cursor_bytes': 35}]
|
||||||
|
----
|
||||||
|
Test 9: visual mode, complete buffer
|
||||||
|
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 32, 'visual_words': 7, 'visual_bytes': 36}]
|
||||||
|
----
|
||||||
|
Test 10: visual mode (empty)
|
||||||
|
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 1, 'visual_words': 0, 'visual_bytes': 1}]
|
||||||
|
----
|
||||||
|
Test 11: visual mode, single line
|
||||||
|
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 13, 'visual_words': 3, 'visual_bytes': 16}]
|
@ -741,6 +741,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1042,
|
||||||
/**/
|
/**/
|
||||||
1041,
|
1041,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user