Git Product home page Git Product logo

tty-file's Introduction

TTY Toolkit logo

TTY::File Gitter

Gem Version Actions CI Build status Maintainability Coverage Status Inline docs

File manipulation utility methods.

TTY::File provides independent file utilities component for TTY toolkit.

Motivation

Though Ruby's File and FileUtils libraries provide very robust apis for dealing with files, this library aims to provide a level of abstraction that is much more convenient, with useful logging capabilities.

Installation

Add this line to your application's Gemfile:

gem "tty-file"

And then execute:

$ bundle

Or install it yourself as:

$ gem install tty-file

Contents

1. Usage

TTY::File.replace_in_file("Gemfile", /gem 'rails'/, "gem 'hanami'")

2. Interface

The following methods are available for creating and manipulating files.

If you wish to silence verbose output use verbose: false. Similarly if you wish to run action without actually triggering any action use noop: true.

2.1. binary?

To check whether a file is a binary file, i.e. image, executable etc. do:

TTY::File.binary?("image.png") # => true

2.2. checksum_file

To generate a checksum for a file, IO object, or String, use checksum_file. By default the MD5 algorithm is used, which can be changed by passing a second argument.

Among the supported message digest algorithms are:

  • sha, sha1, sha224, sha256, sha384, sha512
  • md2, md4, md5

For example, to create a digest for a string using SHA1 do:

TTY::File.checksum_file("Some content\nThe end", "sha1")
# => "289388f187404135e6c15b21460442cf867180dd"

2.3. chmod

To change file modes use chmod, like so:

TTY::File.chmod("filename.rb", 0777)

There are a number of constants available to represent common mode bits such as TTY::File::U_R and TTY::File::O_X, and they can be used as follows:

TTY::File.chmod("filename.rb", TTY::File::U_R | TTY::File::O_X)

Apart from traditional octal number definition for file permissions, you can use the more convenient permission notation used by the Unix chmod command:

TTY::File.chmod("filename.rb", "u=wrx,g+x")

The u, g, and o specify the user, group, and other parts of the mode bits. The a symbol is equivalent to ugo.

2.4. copy_file

Copies a file's contents from a relative source to a relative destination.

TTY::File.copy_file "Gemfile", "Gemfile.bak"

If you provide a block then the file content is yielded:

TTY::File.copy_file("Gemfile", "app/Gemfile") do |content|
  "https://rubygems.org\n" + content
end

If the source file is an ERB template then you can provide a :context in which the file gets evaluated, or if TTY::File gets included as a module then appropriate object context will be used by default. To use :context do:

variables = OpenStruct.new
variables[:foo] = "bar"

TTY::File.copy_file("templates/application.html.erb", context: variables)

You can also specify the template name surrounding any dynamic variables with % to be evaluated:

variables = OpenStruct.new
variables[:file_name] = "foo"

TTY::File.copy_file("templates/%file_name%.rb", context: variables)
# => Creates templates/foo.rb

If the destination is a directory, then copies source inside that directory.

TTY::File.copy_file "docs/README.md", "app"

If the destination file already exists, a prompt menu will be displayed to enquire about action:

If you wish to preserve original owner, group, permission and modified time use :preserve option:

TTY::File.copy_file "docs/README.md", "app", preserve: true

2.5. create_file

To create a file at a given destination with some content use create_file:

TTY::File.create_file "file-a/README.md", content

On collision with already existing file, a menu gets displayed:

   collision  examples/file-a
Overwrite examples/file-a? (enter "h" for help) [y,d,n,q,h]

The d option allows to compare the changes:

--- a/examples/file-a
+++ b/examples/file-a
@@ -1,8 +1,9 @@
 aaaaa
 bbbbb
-ccccc
+xxxxx
+
 ddddd
 eeeee
 fffff
-ggggg
+yyyyy
Overwrite examples/file-a? (enter "h" for help) [y,d,n,q,h]

You can force to always overwrite file with :force option or always skip by providing :skip.

There is examples/overwrite.rb that demonstrates diffing file with new content.

2.6. copy_dir

To recursively copy a directory of files from source to destination location use copy_directory or its alias copy_dir.

Assuming you have the following directory structure:

# doc/
#   subcommands/
#     command.rb.erb
#   README.md
#   %name%.rb

You can copy doc folder to docs by invoking:

TTY::File.copy_directory("doc", "docs", context: ...)

The context needs to respond to name message and given it returns foo value the following directory gets created:

# docs/
#   subcommands/
#     command.rb
#   README.md
#   foo.rb

If you only need to copy top level files use option recursive: false:

TTY::File.copy_directory("doc", "docs", recursive: false)

By passing :exclude option you can instruct the method to ignore any files including the given pattern:

TTY::File.copy_directory("doc", "docs", exclude: "subcommands")

2.7. create_dir

To create directory use create_directory or its alias create_dir passing as a first argument file path:

TTY::File.create_dir("/path/to/directory")

Or a data structure describing the directory tree including any files with or without content:

tree =
  "app" => [
    "README.md",
    ["Gemfile", "gem 'tty-file'"],
    "lib" => [
      "cli.rb",
      ["file_utils.rb", "require 'tty-file'"]
    ]
    "spec" => []
  ]
TTY::File.create_dir(tree)
# =>
# app
# app/README.md
# app/Gemfile
# app/lib
# app/lib/cli.rb
# app/lib/file_utils.rb
# app/spec

As a second argument you can provide a parent directory, otherwise current directory will be assumed:

TTY::File.create_dir(tree, "/path/to/parent/dir")

2.8. diff_files

To compare files line by line in a system independent way use diff, or diff_files:

print TTY::File.diff_files("file-a", "file-b")

Printing output to console would result in:

        diff  examples/file-a and examples/file-b
--- examples/file-a
+++ examples/file-b
@@ -1,8 +1,9 @@
 aaaaa
 bbbbb
-ccccc
+xxxxx
+
 ddddd
 eeeee
 fffff
-ggggg
+yyyyy

You can also pass additional parameters such as:

  • :format - accepted values are :unified, :old, :context and :ed. Defaults to :unified as seen in the output above - similar to git tool.
  • :lines - how many extra lines to include in the output around the compared lines. Defaults to 3 lines.
  • :threshold - set maximum file size in bytes. By default files larger than 10Mb are no processed.
  • :header - controls display of two-line files comparison. By default true.

Changing format to :old, removing context lines and skipping log output:

TTY::File.diff_files("file_a", "file_b", format: :old, lines: 0, verbose: false)

Results in the following output:

<<< examples/file-a
>>> examples/file-b
3c3,4
< ccccc
---
> xxxxx
>

7c8
< ggggg
---
> yyyyy

In addition, you can perform a comparison between a file and a string or between two strings. For example, comparing file with content:

TTY::File.diff_files("file-a", "new\nlong\ntext")

Will output:

        diff  a/examples/file-a and b/examples/file-a
--- a/examples/file-a
+++ b/examples/file-a
@@ -1,8 +1,4 @@
-aaaaa
-bbbbb
-ccccc
-ddddd
-eeeee
-fffff
-ggggg
+new
+long
+text

Please run examples/diff.rb to see how output works.

2.9. download_file

To download a content from a given address and to save at a given relative location do:

TTY::File.download_file("https://gist.github.com/4701967", "doc/README.md")

If you pass a block then the content will be yielded to allow modification:

TTY::File.download_file("https://gist.github.com/4701967", "doc/README.md") do |content|
  content.gsub("\n", " ")
end

By default download_file will follow maximum 3 redirects. This can be changed by passing :limit option:

TTY::File.download_file("https://gist.github.com/4701967", "doc/README.md", limit: 5)
# => raises TTY::File::DownloadError

2.10. inject_into_file

Inject content into a file at a given location and return true when performed successfully, false otherwise.

TTY::File.inject_into_file "filename.rb", "text to add", after: "Code below this line\n"

Or using a block:

TTY::File.inject_into_file "filename.rb", after: "Code below this line\n" do
  "text to add"
end

You can also use Regular Expressions in :after or :before to match file location.

By default, this method will always inject content into file, regardless whether it is already present or not. To change this pass :force set to false to perform check before actually inserting text:

TTY::File.inject_into_file("filename.rb", "text to add", after: "Code below this line\n"

Alternatively, use safe_inject_into_file to check if the text can be safely inserted.

TTY::File.safe_inject_into_file("Gemfile", "gem 'tty'")

The append_to_file and prepend_to_file allow you to add content at the end and the begging of a file.

2.11. replace_in_file

Replace content of a file matching condition by calling replace_in_file or gsub_file, which returns true when substitutions are performed successfully, false otherwise.

TTY::File.replace_in_file "filename.rb", /matching condition/, "replacement"

The replacement content can be provided in a block

TTY::File.gsub_file "filename.rb", /matching condition/ do
  "replacement"
end

2.12. append_to_file

Appends text to a file and returns true when performed successfully, false otherwise. You can provide the text as a second argument:

TTY::File.append_to_file("Gemfile", "gem 'tty'")

Or inside a block:

TTY::File.append_to_file("Gemfile") do
  "gem 'tty'"
end

By default, this method will always append content regardless whether it is already present or not. To change this pass :force set to false to perform check before actually appending:

TTY::File.append_to_file("Gemfile", "gem 'tty'", force: false)

Alternatively, use safe_append_to_file to check if the text can be safely appended.

TTY::File.safe_append_to_file("Gemfile", "gem 'tty'")

2.13. prepend_to_file

Prepends text to a file and returns true when performed successfully, false otherwise. You can provide the text as a second argument:

TTY::File.prepend_to_file("Gemfile", "gem 'tty'")

Or inside a block:

TTY::File.prepend_to_file("Gemfile") do
  "gem 'tty'"
end

By default, this method will always prepend content regardless whether it is already present or not. To change this pass :force set to false to perform check before actually prepending:

TTY::File.prepend_to_file("Gemfile", "gem 'tty'", force: false)

Alternatively, use safe_prepend_to_file to check if the text can be safely appended.

TTY::File.safe_prepend_to_file("Gemfile", "gem 'tty'")

2.14. remove_file

To remove a file do:

TTY::File.remove_file "doc/README.md"

You can also pass in :force to remove file ignoring any errors:

TTY::File.remove_file "doc/README.md", force: true

2.15. tail_file

To read the last 10 lines from a file do:

TTY::File.tail_file "doc/README.md"
# => ["## Copyright", "Copyright (c) 2016-2017", ...]

You can also pass a block:

TTY::File.tail_file("doc/README.md") do |line|
  puts line
end

To change how many lines are read pass a second argument:

TTY::File.tail_file("doc/README.md", 15)

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/tty-file. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Copyright

Copyright (c) 2016 Piotr Murach. See LICENSE for further details.

tty-file's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

tty-file's Issues

TTY::File.binary? fails if the file contains a UTF8 character at byte 4096

Describe the problem

TTY::File.binary? reads only the first 4096 bytes of a file to detect if it's binary. If a UTF8 text file happens to contain a character at the boundary of bytes 4096 and 4097 then it gets split and the file is no longer a valid text file and thus gets marked as binary.

Steps to reproduce the problem

Get the example text file here

TTY::File.binary?('reproduce_tty_bug.txt')

Actual behaviour

true

Expected behaviour

false

Describe your environment

  • OS version: MacOS 10.14.6
  • Ruby version: 2.6.3
  • TTY::File version: 0.7.1

As an aside, I also noticed a small bug on line 367 of that same file: file_a in the error message should be file_b

chmod doesn't seem to accept "+x"

Are you in the right place?

I hope so!

Describe the problem

TTY::File.chmod doesn't respect +x.

Steps to reproduce the problem

irb(main):024:0> sprintf "%04o", (File.stat('foo.txt').mode & 07777)
=> "0644"
irb(main):025:0> TTY::File.chmod 'foo.txt', '+x', verbose: false
=> ["foo.txt"]
irb(main):026:0> sprintf "%04o", (File.stat('foo.txt').mode & 07777)
=> "0644"

Actual behaviour

Nothing happens. The permission don't change.

Expected behaviour

I expected TTY::File.chmod to behave similarly to FileUtils:

irb(main):024:0> sprintf "%04o", (File.stat('foo.txt').mode & 07777)
=> "0644"
irb(main):027:0> FileUtils.chmod '+x', 'foo.txt'
=> ["foo.txt"]
irb(main):028:0> sprintf "%04o", (File.stat('foo.txt').mode & 07777)
=> "0755"

Describe your environment

  • OS version: macOS
  • Ruby version: 2.5.3
  • TTY::File version: 0.8.0

CompatibilityError in replace_in_file

Describe the problem

When doing teletype new app
I get an exception in tty-file (omitting the complete stack trace):

7: from ~/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/tty-0.9.1/lib/tty/commands/new.rb:224:in `add_license_to_readme'
...
1: from ~/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/tty-file-0.7.0/lib/tty/file.rb:587:in `replace_in_file'
~/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/tty-file-0.7.0/lib/tty/file.rb:587:in `gsub!': incompatible character encodings: ASCII-8BIT and UTF-8 (Encoding::CompatibilityError)

The issue might belong to the teletype repository, but since one possible change in tty-file fixes the problem, I deemed it more relevant to put it here.

Steps to reproduce the problem

teletype new app

Actual behaviour

Got an exception, incompatible character encodings: ASCII-8BIT and UTF-8 (Encoding::CompatibilityError).

Expected behaviour

No exception generated.

By undoing commit d185080, the expected behaviour was observed. Maybe binary reading and writing of files is important, but it doesn't seem to handle encodings correctly in all cases.

In the function replace_in_file in file.rb, I observed that contents.encoding returned #<Encoding:ASCII-8BIT>, and args[0].encoding returned #<Encoding:US-ASCII>.

Describe your environment

  • OS version: macOS 10.13.6
  • Ruby version: 2.6.2
  • TTY::File version: 0.7.0

Ruby 3.0 compatility

Are you in the right place?

  • For issues or feature requests file a GitHub issue in this repository
  • For general questions or discussion post in Gitter

Describe the problem

I'm trying to update an app from ruby 2.6 to ruby 3.0 and I'm running into problems.

Steps to reproduce the problem

    copy_file(
        source_path
        taget_path,
        context: some_context
    )

Actual behavior

context keyword argument is simply ignored and the ERB interpolation raises errors.

Expected behavior

I expected the context to be used for the ERB interpolation to be done using its binding.

Describe your environment

  • OS version: Mac OS
  • Ruby version: 3.0.1
  • TTY::File version: 0.10.0

multibyte character will be broken when it is divided by block size during comparing

Describe the problem

TTY::File::CompareFiles#call seems read a file by chunk of block size.
When there is a multibyte character (CJK character, emoji, etc) crosses between blocks, the character will be broken.

Steps to reproduce the problem

./diff-j.rb
       diff  4096-a.txt and 4096-aj.txt
--- 4096-a.txt
+++ 4096-aj.txt
@@ -1 +1 @@
-aaa(repeats 4096 times )aaa�
@@ -1 +1 @@
-A
+��い

4096-a.txt

aaa(repeats 4096 times)aaaA

4096-aj.txt

aaa(repeats 4096 times)aaaあい

check

puts TTY::File.diff("4096-a.txt", "4096-aj.txt")

Actual behaviour

Multi byte character is divided by byte, and broken.

�
��い

Expected behaviour

./diff-j.rb
       diff  4096-a.txt and 4096-aj.txt
--- 4096-a.txt
+++ 4096-aj.txt
@@ -1 +1 @@
-aaa(repeats 4096 times )aaa
@@ -1 +1 @@
-A
+あい

It looks hard to solve with current implementation using block reads.

Describe your environment

  • OS version: Debian 11
  • Ruby version: 2.7.4
  • TTY::File version: 0.10.0
    diff-j.zip

[Features request]List directory and files

I want the user to choose a directory, but it's too complicated to implement with
tty-prompt. Can you provide a function to list and select a directory?
Recommend optional parameters: list directory only.

Getting a success indicator in TTY::File.copy_file()

Describe the problem

I noticed that unlike TTY::File.copy_directory(), TTY::File.copy_file() does't return a value on success.
Would be possible that both methods behave similar?

Steps to reproduce the problem

# Need of rescuing the method in order to know about the success 

begin
  TTY::File.copy_file(  ...  )
rescue
  success = false
  ...
else
  success = true
end

Actual behaviour

result = TTY::File.copy_file()
# result == nil in both error and success

Expected behaviour

Equivalent to its 'brother' method TTY::File.copy_directory()

Describe your environment

  • OS version: macOS Big Sur 11.2
  • Ruby version: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin20]
  • TTY version: tty-file-0.10.0

Some file manipulation methods accept Pathname instances, and some don't

Steps to reproduce the problem

TTY::File.create_file(Pathname.pwd/'a.txt')

I know this example doesn't actually need a Pathname instance because of how relative paths work, but there are cases were it is much easier to provide TTY::File methods Pathname instances instead of Strings that indicate relative_paths, and I was surprised when that didn't work in these cases. Moreover, some methods (TTY::File.safe_append_to_file, for instance) that do work when passed Pathname instances.

Actual behaviour

It results in a NoMethodError because Pathname doesn't define gsub.

Expected behaviour

I expected Pathname instances to be accepted in place of file path String instances across the documented TTY::File methods.

Describe your environment

  • OS version: Ubuntu 16.04
  • Ruby version: 2.5.1
  • TTY::File version: 0.7.0

Other notes

I'm more than happy to write the PR for this (making all documented methods that take String paths also take Pathname instances), I'd just like some indication whether it'd be welcome or not.

difference is ignored when it exists after the block size

Describe the problem

If there is a difference after the block size (4096 on my Linux filesystem), it will be ignored.

Steps to reproduce the problem

I created a small test.

./diff.rb
SHA1 sum for 4096-a.txt: 8c92a77e8e627a3977d35e0c4e4bd8a3c30e1a08
SHA1 sum for 4096-b.txt: 74e5a50dfc7a0e68c02396776e395a3ef5eff0a3
        diff  4096-a.txt and 4096-b.txt
No differences found

4096-a.txt

aaa...(repeats 4096 times)..aaaA

4096-b.txt

aaa...(repeats 4096 times)..aaaB

check

TTY::File.diff("4096-a.txt", "4096-b.txt")

Actual behaviour

diff is ignored.

Expected behaviour

The diff check continues after the first block size.

I suspect lib/tty/file/compare_files.rb :32

      def call(file_a, file_b, file_a_path, file_b_path)
        differ = Differ.new(format: @format, context_lines: @context_lines)
        block_size = file_a.lstat.blksize
        file_a_chunk = file_a.read(block_size)
        file_b_chunk = file_b.read(block_size)
        hunks = differ.(file_a_chunk, file_b_chunk)

        return "" if file_a_chunk.empty? && file_b_chunk.empty?
        return "No differences found\n" if hunks.empty? <-- **

It worked when I commented out this line, but not sure what this code intended.

Describe your environment

  • OS version: Debian GNU/Linux 11.1
  • Ruby version:2.7.4
  • TTY::File version:0.10.0
    diff.zip

Teletype subcommand creation causes nil reference error

I cannot use teletype to create a subcommand of a command.
When I do I get an exception

> teletype add contacts phonelist --force                                                                                                                                    136ms
      create  spec/integration/contacts/phonelist_spec.rb
      create  spec/unit/contacts/phonelist_spec.rb
      create  lib/ddca/commands/contacts/phonelist.rb
      create  lib/ddca/templates/contacts/phonelist/.gitkeep
Traceback (most recent call last):
	10: from /Users/jschank/.asdf/installs/ruby/2.5.1/bin/teletype:23:in `<main>'
	 9: from /Users/jschank/.asdf/installs/ruby/2.5.1/bin/teletype:23:in `load'
	 8: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/tty-0.8.1/exe/teletype:14:in `<top (required)>'
	 7: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor/base.rb:466:in `start'
	 6: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor.rb:387:in `dispatch'
	 5: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor/invocation.rb:126:in `invoke_command'
	 4: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor/command.rb:27:in `run'
	 3: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/tty-0.8.1/lib/tty/cli.rb:88:in `add'
	 2: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/tty-0.8.1/lib/tty/commands/add.rb:131:in `execute'
	 1: from /Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/tty-file-0.6.0/lib/tty/file.rb:512:in `inject_into_file'
/Users/jschank/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/tty-file-0.6.0/lib/tty/file.rb:512:in `escape': no implicit conversion of nil into String (TypeError)

It doesn't matter if I try to define parameters or not. I met this problem when I tried a more complex call:

> teletype add contacts phone_list --desc "Color code the phone extension list" --args contacts_file extension_xslx

Ultimately resulted in the same exception, from the same place

append_to_file does nothing if line matches what's already in destination file

Trying to append a line (which happens to already exist in destination file) returns false, and skips appending altogether. This created a lot of confusion for me in instances such as:

        TTY::File.append_to_file(file) do
          "\n"
        end

Where "\n" already exists somewhere in 'file' and tty-file decided to skip appending. From debugger output it looks like we're jumping into 'inject_into_file' and subsequently 'replace_in_file' to do the actual appending, but 'replace_in_file' does a regex match and skips appending if found.

[556, 565] in /Users/ming/.rvm/gems/ruby-2.4.0/gems/tty-file-0.6.0/lib/tty/file.rb
   556: 
   557:       log_status(:replace, relative_path, options.fetch(:verbose, true),
   558:                                           options.fetch(:color, :green))
   559:       return false if options[:noop]
   560: 
=> 561:       if !(contents =~ /^#{match}(\r?\n)*/m) || options[:force]
   562:         status = contents.gsub!(*args, &block)
   563:         if !status.nil?
   564:           ::File.open(relative_path, 'wb') do |file|
   565:             file.write(contents)

I've been able to work around the issue by simply doing a

        TTY::File.append_to_file(file, force: true) do
          "\n"
        end

but it took a bit of time in the debugger trying to figure out why append_to_file was actually skipping arbitrary lines that I was trying to append.

I'd like to suggest that append_to_file could default to a behavior similar to force: true, so that it skips checking whether the line already exists. Potentially append_to_file could be a forced append, while append_to_file(file, if_new: true) could follow the existing behavior. I think that could be a lot more intuitive for new users.

Append, Prepend, Replace - dont seem to work

Hi,

Trying this lovely gem on Ubuntu 16, with this script:

# test.rb
require 'tty-file'

# replace me

tty = TTY::File
tty.inject_into_file 'test.rb', "# injected\n\n", after: "TTY::File\n"
tty.replace_in_file 'test.rb', /replace me/, "replaced"
tty.prepend_to_file 'test.rb', "# prepended"
tty.append_to_file 'test.rb', "# appended"

Only the inject works, the rest wont.

Here is a screencast:
asciicast

Not sure what I am doing wrong.

Ruby version: ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]

TTY::File output brakes TTY::Spinner

Working on a Gem.
Just found this behaviour:

Gem versions:
tty-file ~> 0.6.0
tty-spinner ~> 0.8.0

Example code:

spinner.auto_run
TTY::File.create_dir(tree, path)
spinner.success

Example output:

#  ⠙ creating directories
#      create  app
#      create  app/Gemfile
#  ✔ creating directories

I've tried wrapping TTY::File block inside spinner.run block. But then I don't have access to my instance methods/variables.

Workaround is to turn verbose output off.
Just wish verbose output could somehow be nicely integrated with spinner.
Though I'm not sure how I'd even implement that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.