string-mutator
v0.2.0
Published
Perform mutation operations on text strings (or text files). Useful for (simple) automatic code refactorings f.ex in code generators
Downloads
14
Maintainers
Readme
Perform mutation operations on text strings (or text files). Useful for (simple) automatic code refactorings f.ex in code generators.
Getting Started
Install the module with: npm install string-mutator
Install with cli command
$ npm install -g string-mutator
$ string-mutator --help
$ string-mutator --version
Browserify
$ npm run-script browser
Documentation
Quick start
var mutators = require('mutators');
var sm = mutators.string; // string mutator
var fm = mutators.file; // file mutator
var msg = "Peter has 8 dollars and Jane has 15"
// String mutator
sm.last('Jane has 15').remove().on(msg);
// using content
sm.content(msg).last(/\d+/g).replaceWith('32');
// File mutator - performing string mutations
fm.readFile('test/files/test.txt').perform(function() {
return this.first(/\d+/).prepend('$');
}).write();
console.log('wrote', written, res.lastWritten);
res.write(res.original);
String mutator API
The string mutation API uses chaining. To start a chain, use any of:
- first(matchExpr)
- last(matchExpr)
- content(text)
first and last
The first
and last
functions each take a matching expression that can be a simple string or a regular expression.
The result can chained with any of:
- append
- prepend
- replaceWith
- remove
append and prepend
sm.first(matchExpr).append('<FOUND>', target);
chaining
Both append
and prepend
can be chained with to
like this
sm.first(matchExpr).append("\nEND").to(target);
relaceWith and remove
sm.first(matchExpr).remove(target);
chaining
replace
and remove
can be chained with on
like this:
sm.first(matchExpr).replaceWith(something).on(target);
first.prepend
var sm = require('string-mutator');
var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.first(/\d+/g).prepend('$', msg);
// => "Peter has $8 dollars and Jane has 15"
The following pattern valid for any prepend/append action.
`(text).to(content)*``
append(text).to(content)
or prepend(text).to(content)
var sm = require('../lib/string-mutator.js');
var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.first(/\d+/g).prepend('$').to(msg);
// => "Peter has $8 dollars and Jane has 15"
first.append
var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.first(/\d+/g).append('$', msg);
res = sm.first(/\d+/g).append('$').to(msg);
// => "Peter has 8$ dollars and Jane has 15"
last.prepend
var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.last(/\d+/g).prepend('$', msg);
// res = sm.last(/\d+/g).prepend('$').to(msg);
// => "Peter has 8 dollars and Jane has $15");
last.append
var msg = "Peter has 8 dollars and Jane has 15$"
var res = sm.last(/\d+/g).append('$', msg);
// res = sm.last(/\d+/g).append('$').to(msg);
// => "Peter has 8 dollars and Jane has 15$");
replaceWith
var msg = "Peter has 8 dollars and Jane has 15$"
var res = sm.last(/\d+/g).replaceWith('42', msg);
res = sm.first(/\d+/g).replaceWith('42').on(msg);
// => "Peter has 8 dollars and Jane has 42");
remove
Replace match with empty content ;)
var msg = "Peter has 8 dollars and Jane has 15"
var res = sm.last('and Jane has 15').remove(msg);
sm.last(/\d+/g).remove().on(msg);
// => "Peter has 8 dollars");
Content
An alternative is to start off by wrapping the text in a content
object
Content can be chained with any of the following:
- first
- last
- before
- after
- between
- prependTxt
- appendTxt
var msg = "Peter has 8 dollars and Jane has 15"
sm.content(msg).last('Jane has 15').remove();
// => "Peter has 8 dollars");
Before
before
is chained on a content
object and returns a new content
object with the text before a match. Optionally it can take a matcher indicator string, which can be set to 'first' or 'last' (effectively: "before first" or "before last")
var msg = "Peter has 15 dollars, Jane has 15 and Paul has 32"
sm.content(msg).before(/Jane/).last(/\d+/g).replaceWith('20');
// => Peter has 20 dollars, Jane has 15 and Paul has 32
chaining prependTxt
on before
prepends the text before the match.
msg = "Peter have 12 dollars, Paul"
var res = sm.content(msg).before(/Paul/).prependTxt('Tina has 7.').result;
// => Peter have 12 dollars, Tina has 7
Using `mergeRest()``
msg = "Peter have 12 dollars, Paul"
var res = sm.content(msg).before(/Paul/).prependTxt('Tina has 7 and').mergeRest();
// => Peter have 12 dollars, Tina has 7 and Paul
before last
before
(and after
) also take an options hash for further control.
The match: 'last'
option can be used to find the last match within the scope.
msg = "Peter have 12 dollars, Paul is here Paul goes back"
var res = sm.content(msg).before(/Paul/, {include: true, match: 'last'}).prependTxt('Tina has 7 and').mergeRest();
// => Peter have 12 dollars, Paul is here Tina has 7 and Paul goes back
For convenience beforeLast
and afterLast
methods are also available.
`var res = sm.content(msg).beforeLast(/Paul/)``
After
Same as before
but instead "after" ;)
If in doubt, see the test suite in the /test
folder.
Between
between
is chained on a content
object and returns a new content
object with the text between two matches.
var msg = "Peter has 15 dollars, Jane has 15 and Paul has 32 or 15"
sm.content(msg).between(/Peter/).and(/Paul/).last(/\d+/g).replaceWith('20');
// => Peter has 15 dollars, Jane has 20 and Paul has 32 or 15
inclusive
Both between
, and
are exclusive by default.
You can now also use an options hash {include: true}
to be inclusive.
This option can also be used with before
and after
.
var msg = "Peter has 15 dollars, Jane has 15 and Paul has 32 or 15"
sm.content(msg).between(/Peter/, {include: true}).and(/Paul/, {include: true}).result;
// => Peter has 15 dollars, Jane has 20 and Paul
Shorthand inclusive:
`sm.content(msg).betweenIncl(/Peter/).andIncl(/Paul/)``
prependTxt
Adds text at beginning of content
`sm.content("Kristian").prependTxt('Hello, Sir ')``
appendTxt
Adds text at the end of content
sm.content("Paula").appendTxt(', says Goodbye')
Status
All tests pass :)
More advanced operations
For even more string manipulation, I recommend splitting a string into its multiple parts using a split
function, then iterating through them and using this API on each part, then joining them back together.
You are most welcome to propose a nice API to facilitate this.
File mutator API
File mutation always starts with readFile
var fileMutateObj = fm.readFile('test/files/test.txt');
The result of readFile
should always be chained with perform
, which performs the string mutation on the content read.
perform
wraps the read content in a content
object (see: String mutator API) which becomes this
in the context/scope of the function.
fm.readFile('test/files/test.txt').perform(function() {
return this.first(/\d+/).prepend('$');
})
The result of the perform
mutation can be chained with any of:
- write([newContent])
- writeFile(fileName, [newContent])
- read()
- lastWritten
- original
Complete example:
fm.readFile('test/files/test.txt').perform(function() {
return this.first(/\d+/).prepend('$');
}).write();
console.log('wrote', written, res.lastWritten);
res.write(res.original);
res.writeFile('another_file.txt');
TODO
Cleanup and Refactor!!! Lot's of duplication :(
Add more customizability than simply first/last. It would be sweet if user could pass a function that selects one or more matches to operate on/from.
Contributing
Add unit tests for any new or changed functionality. Lint and test your code using Grunt.
License
Copyright (c) 2014 Kristian Mandrup
Licensed under the MIT license.